Add debug draw addon, implement basic input event
This commit is contained in:
parent
58000dcc1f
commit
2433845df7
|
@ -120,6 +120,7 @@ Thus I've decided to use a custom event system that is similar to the one used i
|
|||
| Group | Description |
|
||||
| -- | -- |
|
||||
| `ui_focus` | The element can be focused |
|
||||
| `ui_focus_skip` | The focus will not be reset. Useful for keyboard |
|
||||
|
||||
|
||||
### Functions
|
||||
|
|
21
addons/debug_draw_3d/LICENSE
Normal file
21
addons/debug_draw_3d/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 DmitriySalnikov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the Software), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, andor sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
183
addons/debug_draw_3d/README.md
Normal file
183
addons/debug_draw_3d/README.md
Normal file
|
@ -0,0 +1,183 @@
|
|||
![icon](/images/icon.png)
|
||||
|
||||
# Debug drawing utility for Godot
|
||||
|
||||
This is an add-on for debug drawing in 3D and for some 2D overlays, which is written in `C++` and can be used with `GDScript` or `C#`.
|
||||
|
||||
Based on my previous addon, which was developed only for C# https://github.com/DmitriySalnikov/godot_debug_draw_cs, and which was inspired by Zylann's GDScript addon https://github.com/Zylann/godot_debug_draw
|
||||
|
||||
## [Godot 3 version](https://github.com/DmitriySalnikov/godot_debug_draw_3d/tree/godot_3)
|
||||
|
||||
## Support me
|
||||
|
||||
Your support adds motivation to develop my public projects.
|
||||
|
||||
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/I2I53VZ2D)
|
||||
|
||||
[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://paypal.me/dmitriysalnikov)
|
||||
|
||||
[<img src="https://upload.wikimedia.org/wikipedia/commons/8/8f/QIWI_logo.svg" alt="qiwi" width=90px/>](https://qiwi.com/n/DMITRIYSALNIKOV)
|
||||
|
||||
## Features
|
||||
|
||||
3D:
|
||||
|
||||
* Arrow
|
||||
* Billboard opaque square
|
||||
* Box
|
||||
* Camera Frustum
|
||||
* Cylinder
|
||||
* Gizmo
|
||||
* Grid
|
||||
* Line
|
||||
* Line Path
|
||||
* Line with Arrow
|
||||
* Points
|
||||
* Position 3D (3 crossing axes)
|
||||
* Sphere
|
||||
|
||||
2D:
|
||||
|
||||
* **[Work in progress]**
|
||||
|
||||
Overlay:
|
||||
|
||||
* Text (with grouping and coloring)
|
||||
* FPS Graph
|
||||
* Custom Graphs
|
||||
|
||||
Precompiled for:
|
||||
|
||||
* Windows
|
||||
* Linux
|
||||
* macOS
|
||||
* Android
|
||||
|
||||
## Download
|
||||
|
||||
To download, use the [Godot Asset Library](https://godotengine.org/asset-library/asset/1766) or download the archive by clicking the button at the top of the main repository page: `Code -> Download ZIP`, then unzip it to your project folder. Or use one of the stable versions from the [GitHub Releases](https://github.com/DmitriySalnikov/godot_debug_draw_3d/releases) page (just download one of the `Source Codes` in assets).
|
||||
|
||||
## Usage
|
||||
|
||||
* Close editor
|
||||
* Copy `addons/debug_draw_3d` to your `addons` folder, create it if the folder doesn't exist
|
||||
* Launch editor
|
||||
|
||||
### C\#
|
||||
|
||||
When you start the engine for the first time, bindings for `C#` will be generated automatically. If this does not happen, you can manually generate them through the `Project - Tools - Debug Draw` menu.
|
||||
|
||||
![project_tools_menu](/images/project_tools_menu.png)
|
||||
|
||||
## Examples
|
||||
|
||||
More examples can be found in the `examples_dd3d/` folder.
|
||||
|
||||
Simple test:
|
||||
|
||||
```gdscript
|
||||
func _process(delta: float) -> void:
|
||||
var _time = Time.get_ticks_msec() / 1000.0
|
||||
var box_pos = Vector3(0, sin(_time * 4), 0)
|
||||
var line_begin = Vector3(-1, sin(_time * 4), 0)
|
||||
var line_end = Vector3(1, cos(_time * 4), 0)
|
||||
|
||||
DebugDraw3D.draw_box(box_pos, Vector3(1, 2, 1), Color(0, 1, 0))
|
||||
DebugDraw3D.draw_line(line_begin, line_end, Color(1, 1, 0))
|
||||
DebugDraw2D.set_text("Time", _time)
|
||||
DebugDraw2D.set_text("Frames drawn", Engine.get_frames_drawn())
|
||||
DebugDraw2D.set_text("FPS", Engine.get_frames_per_second())
|
||||
DebugDraw2D.set_text("delta", delta)
|
||||
```
|
||||
|
||||
```csharp
|
||||
public override void _Process(float delta)
|
||||
{
|
||||
var _time = Time.GetTicksMsec() / 1000.0f;
|
||||
var box_pos = new Vector3(0, Mathf.Sin(_time * 4f), 0);
|
||||
var line_begin = new Vector3(-1, Mathf.Sin(_time * 4f), 0);
|
||||
var line_end = new Vector3(1, Mathf.Cos(_time * 4f), 0);
|
||||
|
||||
DebugDraw3D.DrawBox(box_pos, new Vector3(1, 2, 1), new Color(0, 1, 0));
|
||||
DebugDraw3D.DrawLine(line_begin, line_end, new Color(1, 1, 0));
|
||||
DebugDraw2D.SetText("Time", _time);
|
||||
DebugDraw2D.SetText("Frames drawn", Engine.GetFramesDrawn());
|
||||
DebugDraw2D.SetText("FPS", Engine.GetFramesPerSecond());
|
||||
DebugDraw2D.SetText("delta", delta);
|
||||
}
|
||||
```
|
||||
|
||||
![screenshot_1](/images/screenshot_1.png)
|
||||
|
||||
## API
|
||||
|
||||
A list of all functions is available in the documentation inside the editor.
|
||||
![screenshot_4](/images/screenshot_4.png)
|
||||
|
||||
Besides `DebugDraw2D/3D`, you can also use `Dbg2/3`.
|
||||
|
||||
```gdscript
|
||||
DebugDraw3D.draw_box_xf(Transform3D(), Color.GREEN)
|
||||
Dbg3.draw_box_xf(Transform3D(), Color.GREEN)
|
||||
|
||||
DebugDraw2D.set_text("delta", delta)
|
||||
Dbg2.set_text("delta", delta)
|
||||
```
|
||||
|
||||
But unfortunately at the moment `GDExtension` does not support adding documentation.
|
||||
|
||||
## Exporting a project
|
||||
|
||||
Most likely, when exporting a release version of a game, you don't want to export the debug library along with it. But since there is still no `Conditional Compilation` in `GDScript`, so I decided to create a `dummy` library that has the same API as a regular library, but has minimal impact on performance, even if calls to its methods occur. The `dummy` library is used by default in the release version. However if you need to use debug rendering in the release version, then you can add the `forced_dd3d` feature when exporting. In this case, the release library with all the functionality will be used.
|
||||
|
||||
![export_features](/images/export_features.png)
|
||||
|
||||
In C#, these tags are not taken into account at compile time, so the Release build will use Runtime checks to disable draw calls. If you want to avoid this, you can manually specify the `FORCED_DD3D` symbol.
|
||||
|
||||
![csharp_compilation_symbols](/images/csharp_compilation_symbols.png)
|
||||
|
||||
## Known issues and limitations
|
||||
|
||||
Enabling occlusion culing can lower fps instead of increasing it. At the moment I do not know how to speed up the calculation of the visibility of objects.
|
||||
|
||||
The text in the keys and values of a text group cannot contain multi-line strings.
|
||||
|
||||
The entire text overlay can only be placed in one corner, unlike `DataGraphs`.
|
||||
|
||||
[Frustum of Camera3D does not take into account the window size from ProjectSettings](https://github.com/godotengine/godot/issues/70362).
|
||||
|
||||
**The version for Godot 4.0 requires explicitly specifying the exact data types, otherwise errors may occur.**
|
||||
|
||||
## More screenshots
|
||||
|
||||
`DebugDrawDemoScene.tscn` in editor
|
||||
![screenshot_2](/images/screenshot_2.png)
|
||||
|
||||
`DebugDrawDemoScene.tscn` in play mode
|
||||
![screenshot_3](/images/screenshot_3.png)
|
||||
|
||||
## Build
|
||||
|
||||
As well as for the engine itself, you will need to configure the [environment](https://docs.godotengine.org/en/4.1/contributing/development/compiling/index.html).
|
||||
And also you need to apply several patches:
|
||||
|
||||
```bash
|
||||
cd godot-cpp
|
||||
git apply --ignore-space-change --ignore-whitespace ../patches/always_build_fix.patch
|
||||
git apply --ignore-space-change --ignore-whitespace ../patches/1165.patch
|
||||
# Optional
|
||||
## Build only the necessary classes
|
||||
git apply --ignore-space-change --ignore-whitespace ../patches/godot_cpp_exclude_unused_classes.patch
|
||||
## Faster build
|
||||
git apply --ignore-space-change --ignore-whitespace ../patches/unity_build.patch
|
||||
```
|
||||
|
||||
Then you can just run scons as usual:
|
||||
|
||||
```bash
|
||||
# build for the current system.
|
||||
# target=editor is used for both the editor and the debug template.
|
||||
scons target=editor dev_build=yes debug_symbols=yes
|
||||
# build for the android. ANDROID_NDK_ROOT is required in your environment variables.
|
||||
scons platform=android target=template_release arch=arm64v8
|
||||
```
|
55
addons/debug_draw_3d/debug_draw_3d.gdextension
Normal file
55
addons/debug_draw_3d/debug_draw_3d.gdextension
Normal file
|
@ -0,0 +1,55 @@
|
|||
[configuration]
|
||||
|
||||
entry_symbol = "debug_draw_3d_library_init"
|
||||
compatibility_minimum = "4.1"
|
||||
|
||||
[dependencies]
|
||||
|
||||
# example.x86_64 = { "relative or absolute path to the dependency" : "the path relative to the exported project", }
|
||||
|
||||
macos = { }
|
||||
windows.x86_64 = { }
|
||||
linux.x86_64 = { }
|
||||
|
||||
android.arm32 = { }
|
||||
android.arm64 = { }
|
||||
android.x86_32 = { }
|
||||
android.x86_64 = { }
|
||||
|
||||
macos.template_release = { }
|
||||
windows.template_release.x86_64 = { }
|
||||
linux.template_release.x86_64 = { }
|
||||
|
||||
android.template_release.arm32 = { }
|
||||
android.template_release.arm64 = { }
|
||||
android.template_release.x86_32 = { }
|
||||
android.template_release.x86_64 = { }
|
||||
|
||||
[libraries]
|
||||
|
||||
macos = "libs/libdd3d.macos.editor.universal.dylib"
|
||||
windows.x86_64 = "libs/libdd3d.windows.editor.x86_64.dll"
|
||||
linux.x86_64 = "libs/libdd3d.linux.editor.x86_64.so"
|
||||
|
||||
android.arm32 = "libs/libdd3d.android.template_debug.arm32.so"
|
||||
android.arm64 = "libs/libdd3d.android.template_debug.arm64.so"
|
||||
android.x86_32 = "libs/libdd3d.android.template_debug.x86_32.so"
|
||||
android.x86_64 = "libs/libdd3d.android.template_debug.x86_64.so"
|
||||
|
||||
macos.template_release = "libs/libdd3d.macos.template_release.universal.dylib"
|
||||
windows.template_release.x86_64 = "libs/libdd3d.windows.template_release.x86_64.dll"
|
||||
linux.template_release.x86_64 = "libs/libdd3d.linux.template_release.x86_64.so"
|
||||
|
||||
android.template_release.arm32 = "libs/libdd3d.android.template_release.arm32.so"
|
||||
android.template_release.arm64 = "libs/libdd3d.android.template_release.arm64.so"
|
||||
android.template_release.x86_32 = "libs/libdd3d.android.template_release.x86_32.so"
|
||||
android.template_release.x86_64 = "libs/libdd3d.android.template_release.x86_64.so"
|
||||
|
||||
macos.template_release.forced_dd3d = "libs/libdd3d.macos.template_release.universal.enabled.dylib"
|
||||
windows.template_release.x86_64.forced_dd3d = "libs/libdd3d.windows.template_release.x86_64.enabled.dll"
|
||||
linux.template_release.x86_64.forced_dd3d = "libs/libdd3d.linux.template_release.x86_64.enabled.so"
|
||||
|
||||
android.template_release.arm32.forced_dd3d = "libs/libdd3d.android.template_release.arm32.enabled.so"
|
||||
android.template_release.arm64.forced_dd3d = "libs/libdd3d.android.template_release.arm64.enabled.so"
|
||||
android.template_release.x86_32.forced_dd3d = "libs/libdd3d.android.template_release.x86_32.enabled.so"
|
||||
android.template_release.x86_64.forced_dd3d = "libs/libdd3d.android.template_release.x86_64.enabled.so"
|
0
addons/debug_draw_3d/libs/.gdignore
Normal file
0
addons/debug_draw_3d/libs/.gdignore
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0fb41898f762f555f379bc351a0d2d82bc9cbf3b701a1f9fe8035646ddad44b5
|
||||
size 2928328
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1dfdb52ffe2e428ea0a0b9ff951b986546291f383f37c957d7de4c367f79892f
|
||||
size 2993032
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5c580b7b4d44342c56d1990ab09358b63fa60cf99846a355c86ceb2cb5023b14
|
||||
size 3057172
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b6c2b95269938e60e709539c8166cd9e5f450bd3fbd2b6bdfdf652fca3f594db
|
||||
size 2977744
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1c40f93bd53bc4b132d075f18814b1198e71df6b9f2601c11f0cfbc2494698cf
|
||||
size 1804756
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0181cc7c1a08ecc39de983b1b1e35f66572479da533f744190fa803cbde44612
|
||||
size 2001576
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:24497f5a2ad8a7d99e2acb62d6c526017d7c365f8fd7fd6ae3042d96bd6e980a
|
||||
size 1996072
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6eab3ff00fc2d7347a6b166e67a3800d6117fa84bcfa3317429d6e0bff896654
|
||||
size 2028472
|
3
addons/debug_draw_3d/libs/libdd3d.linux.editor.x86_64.so
Normal file
3
addons/debug_draw_3d/libs/libdd3d.linux.editor.x86_64.so
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9b39c1ca40f0a22e66e742daba8e050884caa7a3ff959824b0c99a7e061fd869
|
||||
size 3806144
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4bfbec2037276c6858cbfc4019bb0381eb9bd83cdcdfcfa3cc802bfc0d5f427b
|
||||
size 3072224
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7efcb3de6de7d5a878c4a221931a94a74f3741a6aeb7d7e9a4f19fb07bf1115c
|
||||
size 2193840
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:818647a1234354725573918ce71972193812dd19d9ffb4bbe35f4a17ff48341f
|
||||
size 5739144
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5bbf87c77f9c9fe6643948257e91f271825a2874172c97cdbd915a6203a6eff3
|
||||
size 3339680
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b0f280b00b057266534e477e4b33e476f108b41d1927d4db39e8d1e3a781adc5
|
||||
size 4689496
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ac3ac3647171c53e2f47564df2e25eff19fbfab8bf763d0078fe1c82476d8761
|
||||
size 1291264
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3d3113daaa53fe431ca8ce55f127c0e41ef4243ab5aadd359dc6d2c63b31f057
|
||||
size 680448
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:af5ae3a80d09e6212d21e4cf608aa38f711d230914918d0f2f427bdcc5488e24
|
||||
size 862208
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:55d5f30db336a8f8f7633743c23e41077d5c1a1b900c475a6d3811746eba3d1b
|
||||
size 141
|
3
assets/materials/ui_element.material
Normal file
3
assets/materials/ui_element.material
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:57f8bfca31acba3de3a15a2b9a88b8afd12f8db9c356f14d906840dcee48d6f6
|
||||
size 1021
|
|
@ -33,13 +33,13 @@ script = ExtResource("1_uvrd4")
|
|||
[node name="XROrigin3D" type="XROrigin3D" parent="."]
|
||||
|
||||
[node name="XRCamera3D" type="XRCamera3D" parent="XROrigin3D"]
|
||||
transform = Transform3D(1, 2.18865e-10, 3.7835e-10, 3.85836e-11, 1, 2.08752e-08, -2.91038e-11, 8.6402e-12, 1, 0.0356344, 0.79808, 0.202806)
|
||||
transform = Transform3D(1, 1.8976e-10, 4.07454e-10, 6.76872e-11, 1, 2.08738e-08, -5.82077e-11, 1.04592e-11, 1, 0.0356618, 0.71033, 0.00564247)
|
||||
|
||||
[node name="XRControllerLeft" parent="XROrigin3D" instance=ExtResource("2_2lraw")]
|
||||
transform = Transform3D(0.999999, -1.39633e-11, 0, 9.48075e-12, 1, 0, 0, 0, 1, -0.355145, 0.550439, -0.477945)
|
||||
|
||||
[node name="XRControllerRight" type="XRController3D" parent="XROrigin3D"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.488349, 0.559219, -0.2988)
|
||||
transform = Transform3D(0.999999, -1.39633e-11, 0, 9.48075e-12, 1, 0, 0, 0, 1, 0.272616, 0.559282, -0.468369)
|
||||
tracker = &"right_hand"
|
||||
pose = &"aim"
|
||||
|
||||
|
@ -66,4 +66,4 @@ transform = Transform3D(0.404247, 0.000180645, 0.914648, 0.00017221, 0.999999, -
|
|||
visible = false
|
||||
|
||||
[node name="Keyboard" parent="." instance=ExtResource("9_e5n3p")]
|
||||
transform = Transform3D(0.5, -6.98186e-12, 0, 4.73988e-12, 0.5, 0, 0, 0, 0.5, -0.00874073, 0.253873, -0.357135)
|
||||
transform = Transform3D(0.499999, -6.98142e-12, 0, 4.74065e-12, 0.5, -2.27374e-13, 0, 2.27374e-13, 0.5, -0.125313, 0.424282, -0.263966)
|
||||
|
|
|
@ -6,6 +6,7 @@ const button_scene = preload("res://content/ui/components/button/button.tscn")
|
|||
@onready var keys = $Keys
|
||||
@onready var caps_button = $Caps
|
||||
@onready var backspace_button = $Backspace
|
||||
@onready var paste_button = $Paste
|
||||
var key_list = [
|
||||
[KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, KEY_ASCIITILDE],
|
||||
[KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, KEY_SLASH],
|
||||
|
@ -57,6 +58,15 @@ func _ready():
|
|||
_emit_event("key_up", KEY_CAPSLOCK)
|
||||
)
|
||||
|
||||
paste_button.on_button_down.connect(func():
|
||||
# There is no KEY_PASTE obviously, so we use KEY_INSERT for now
|
||||
_emit_event("key_down", KEY_INSERT)
|
||||
)
|
||||
|
||||
paste_button.on_button_up.connect(func():
|
||||
_emit_event("key_up", KEY_INSERT)
|
||||
)
|
||||
|
||||
func create_key(key: Key):
|
||||
var button = button_scene.instantiate()
|
||||
|
||||
|
@ -68,7 +78,7 @@ func create_key(key: Key):
|
|||
label.add_to_group("button_label")
|
||||
|
||||
button.set_meta("key", key)
|
||||
|
||||
button.add_to_group("ui_focus_skip")
|
||||
button.add_child(label)
|
||||
|
||||
return button
|
||||
|
|
|
@ -12,7 +12,7 @@ size = Vector3(0.744504, 0.0402036, 0.296009)
|
|||
transform = Transform3D(0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0, 0, 0)
|
||||
script = ExtResource("1_maojw")
|
||||
|
||||
[node name="Backspace" parent="." instance=ExtResource("1_xdpwr")]
|
||||
[node name="Backspace" parent="." groups=["ui_focus_skip"] instance=ExtResource("1_xdpwr")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.66, 0, 0.02)
|
||||
metadata/key = 4194308
|
||||
|
||||
|
@ -21,7 +21,7 @@ transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0.0
|
|||
pixel_size = 0.001
|
||||
text = "back"
|
||||
|
||||
[node name="Caps" parent="." instance=ExtResource("1_xdpwr")]
|
||||
[node name="Caps" parent="." groups=["ui_focus_skip"] instance=ExtResource("1_xdpwr")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.06, 0, 0.15)
|
||||
toggleable = true
|
||||
|
||||
|
@ -30,6 +30,14 @@ transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0.0
|
|||
pixel_size = 0.001
|
||||
text = "caps"
|
||||
|
||||
[node name="Paste" parent="." groups=["ui_focus_skip"] instance=ExtResource("1_xdpwr")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.66, 0, 0.18)
|
||||
|
||||
[node name="Label3D" type="Label3D" parent="Paste"]
|
||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0.012, 0)
|
||||
pixel_size = 0.001
|
||||
text = "paste"
|
||||
|
||||
[node name="Keys" type="Node3D" parent="."]
|
||||
script = ExtResource("3_mx544")
|
||||
columns = 11
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
@tool
|
||||
extends StaticBody3D
|
||||
class_name Button3D
|
||||
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
[gd_scene load_steps=8 format=3 uid="uid://bsjqdvkt0u87c"]
|
||||
|
||||
[ext_resource type="Script" path="res://content/ui/components/button/button.gd" id="1_74x7g"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_peqek"]
|
||||
albedo_color = Color(0.151534, 0.211909, 0.619523, 1)
|
||||
[ext_resource type="Material" uid="uid://bujy3egn1oqac" path="res://assets/materials/ui_element.material" id="2_h7ln4"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_jwpm5"]
|
||||
resource_local_to_scene = true
|
||||
material = SubResource("StandardMaterial3D_peqek")
|
||||
material = ExtResource("2_h7ln4")
|
||||
size = Vector3(0.05, 0.02, 0.05)
|
||||
|
||||
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_o4j7g"]
|
||||
|
|
85
content/ui/components/input/input.gd
Normal file
85
content/ui/components/input/input.gd
Normal file
|
@ -0,0 +1,85 @@
|
|||
extends StaticBody3D
|
||||
|
||||
@onready var caret: MeshInstance3D = $Label/Caret
|
||||
@onready var label: Label3D = $Label
|
||||
@onready var animation: AnimationPlayer = $AnimationPlayer
|
||||
|
||||
var text: String = "Hello World":
|
||||
set(value):
|
||||
var old_text = text
|
||||
text = value
|
||||
label.text = value
|
||||
gap_offsets = _calculate_text_gaps()
|
||||
caret_position += text.length() - old_text.length()
|
||||
|
||||
var keyboard_input: bool = false
|
||||
var gap_offsets = []
|
||||
var caret_position: int = 3:
|
||||
set(value):
|
||||
caret_position = clampi(value, 0, text.length())
|
||||
caret.position.x = gap_offsets[caret_position]
|
||||
|
||||
func _ready():
|
||||
EventSystem.on_key_down.connect(func(event):
|
||||
if EventSystem.is_focused(self) == false:
|
||||
return
|
||||
|
||||
text = EventKey.key_to_string(event.key, event.shift_pressed, text.substr(0, caret_position)) + text.substr(caret_position, text.length())
|
||||
)
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventKey && EventSystem.is_focused(self) && event.pressed:
|
||||
if event.keycode == KEY_F1:
|
||||
keyboard_input = !keyboard_input
|
||||
return
|
||||
|
||||
if keyboard_input:
|
||||
text = EventKey.key_to_string(event.keycode, event.shift_pressed, text.substr(0, caret_position)) + text.substr(caret_position, text.length())
|
||||
|
||||
func _process(_delta):
|
||||
if get_tree().debug_collisions_hint && OS.get_name() != "Android":
|
||||
_draw_debug_text_gaps()
|
||||
|
||||
func _calculate_caret_pos(click_pos_x: float):
|
||||
for i in range(1, gap_offsets.size()):
|
||||
var left = gap_offsets[i]
|
||||
|
||||
if click_pos_x < left:
|
||||
return i - 1
|
||||
|
||||
return gap_offsets.size() - 1
|
||||
|
||||
|
||||
func _on_focus_in(event):
|
||||
gap_offsets = _calculate_text_gaps()
|
||||
|
||||
var pos_x = label.to_local(event.ray.get_collision_point()).x
|
||||
|
||||
caret_position = _calculate_caret_pos(pos_x)
|
||||
animation.play("blink")
|
||||
|
||||
func _on_focus_out(_event):
|
||||
animation.stop()
|
||||
caret.hide()
|
||||
|
||||
func _calculate_text_gaps():
|
||||
var font = label.get_font()
|
||||
var offsets = [0.0]
|
||||
|
||||
var offset = 0.0
|
||||
for i in range(text.length()):
|
||||
var character = text[i]
|
||||
var size = font.get_string_size(character, HORIZONTAL_ALIGNMENT_CENTER, -1, label.font_size)
|
||||
|
||||
offset += size.x * label.pixel_size
|
||||
offsets.append(offset)
|
||||
|
||||
return offsets
|
||||
|
||||
func _draw_debug_text_gaps():
|
||||
for offset in gap_offsets:
|
||||
DebugDraw3D.draw_line(
|
||||
label.to_global(Vector3(offset, -0.01, 0)),
|
||||
label.to_global(Vector3(offset, 0.01, 0)),
|
||||
Color(1, 0, 0),
|
||||
)
|
80
content/ui/components/input/input.tscn
Normal file
80
content/ui/components/input/input.tscn
Normal file
|
@ -0,0 +1,80 @@
|
|||
[gd_scene load_steps=10 format=3 uid="uid://blrhy2uccrdn4"]
|
||||
|
||||
[ext_resource type="Material" uid="uid://bujy3egn1oqac" path="res://assets/materials/ui_element.material" id="1_0kd7r"]
|
||||
[ext_resource type="Script" path="res://content/ui/components/input/input.gd" id="1_uml3t"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_kjbca"]
|
||||
size = Vector3(0.2, 0.006, 0.03)
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_x4yp8"]
|
||||
size = Vector3(0.2, 0.006, 0.03)
|
||||
|
||||
[sub_resource type="SystemFont" id="SystemFont_nbea0"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_2736g"]
|
||||
size = Vector3(0.001, 0.02, 0.001)
|
||||
|
||||
[sub_resource type="Animation" id="Animation_65tpe"]
|
||||
length = 0.001
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Label/Caret:visible")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [true]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_8ny1h"]
|
||||
resource_name = "blink"
|
||||
loop_mode = 1
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Label/Caret:visible")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.5, 1),
|
||||
"transitions": PackedFloat32Array(1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [true, false, true]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_1sy4t"]
|
||||
_data = {
|
||||
"RESET": SubResource("Animation_65tpe"),
|
||||
"blink": SubResource("Animation_8ny1h")
|
||||
}
|
||||
|
||||
[node name="Input" type="StaticBody3D" groups=["ui_focus"]]
|
||||
script = ExtResource("1_uml3t")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.003, 0)
|
||||
material_override = ExtResource("1_0kd7r")
|
||||
mesh = SubResource("BoxMesh_kjbca")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.003, 0)
|
||||
shape = SubResource("BoxShape3D_x4yp8")
|
||||
|
||||
[node name="Label" type="Label3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, -0.096, 0.00618291, 0)
|
||||
pixel_size = 0.0004
|
||||
text = "Hello World"
|
||||
font = SubResource("SystemFont_nbea0")
|
||||
horizontal_alignment = 0
|
||||
|
||||
[node name="Caret" type="MeshInstance3D" parent="Label"]
|
||||
mesh = SubResource("BoxMesh_2736g")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||
libraries = {
|
||||
"": SubResource("AnimationLibrary_1sy4t")
|
||||
}
|
|
@ -24,6 +24,7 @@ font_size = 36
|
|||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.19, 0.01, 0.27)
|
||||
|
||||
[node name="NextPageButton" parent="Buttons" instance=ExtResource("4_tvimg")]
|
||||
focusable = true
|
||||
|
||||
[node name="Decal" type="Decal" parent="Buttons/NextPageButton"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.02, 0)
|
||||
|
@ -35,6 +36,7 @@ script = ExtResource("6_pf8jy")
|
|||
|
||||
[node name="PreviousPageButton" parent="Buttons" instance=ExtResource("4_tvimg")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.08, 0, 0)
|
||||
focusable = true
|
||||
|
||||
[node name="Decal" type="Decal" parent="Buttons/PreviousPageButton"]
|
||||
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0.02, 0)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=16 format=3 uid="uid://c3kdssrmv84kv"]
|
||||
[gd_scene load_steps=17 format=3 uid="uid://c3kdssrmv84kv"]
|
||||
|
||||
[ext_resource type="Script" path="res://content/ui/menu/menu.gd" id="1_ng4u3"]
|
||||
[ext_resource type="PackedScene" uid="uid://crrb0l3ekuotj" path="res://content/ui/menu/edit/edit_menu.tscn" id="4_r2raj"]
|
||||
|
@ -11,6 +11,7 @@
|
|||
[ext_resource type="Texture2D" uid="uid://dyh0ax51xqp8n" path="res://assets/icons/settings_white_24dp.svg" id="9_mel13"]
|
||||
[ext_resource type="PackedScene" uid="uid://c01gkeldvjwtr" path="res://content/ui/menu/room/room_menu.tscn" id="10_u4i1x"]
|
||||
[ext_resource type="PackedScene" uid="uid://c6r4higceibif" path="res://content/ui/menu/settings/settings_menu.tscn" id="11_7wm6b"]
|
||||
[ext_resource type="PackedScene" uid="uid://blrhy2uccrdn4" path="res://content/ui/components/input/input.tscn" id="12_ov3em"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_08du6"]
|
||||
size = Vector3(0.3, 0.01, 0.3)
|
||||
|
@ -236,3 +237,6 @@ mesh = ExtResource("7_f4u4o")
|
|||
libraries = {
|
||||
"": SubResource("AnimationLibrary_s30cd")
|
||||
}
|
||||
|
||||
[node name="Input" parent="." instance=ExtResource("12_ov3em")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.19, 0, -0.04)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
extends Event
|
||||
class_name EventFocus
|
||||
|
||||
var ray: RayCast3D
|
||||
var target: Node
|
||||
var previous_target: Node
|
|
@ -4,13 +4,19 @@ class_name EventKey
|
|||
var key: Key
|
||||
var echo: bool
|
||||
|
||||
static func key_to_string(key: Key, caps: bool = false) -> String:
|
||||
static func key_to_string(key: Key, caps: bool = false, apply_to: String = "") -> String:
|
||||
match key:
|
||||
KEY_ASCIITILDE: return "~"
|
||||
KEY_SLASH: return "/"
|
||||
KEY_BACKSLASH: return "\\"
|
||||
KEY_COLON: return ";"
|
||||
KEY_COMMA: return ","
|
||||
KEY_PERIOD: return "."
|
||||
KEY_MINUS: return "-"
|
||||
_: return OS.get_keycode_string(key).to_upper() if caps else OS.get_keycode_string(key).to_lower()
|
||||
KEY_INSERT: apply_to += DisplayServer.clipboard_get()
|
||||
KEY_BACKSPACE: apply_to = apply_to.substr(0, apply_to.length() - 1)
|
||||
KEY_SPACE: apply_to += " "
|
||||
KEY_ASCIITILDE: apply_to += "~"
|
||||
KEY_SLASH: apply_to += "/"
|
||||
KEY_BACKSLASH: apply_to += "\\"
|
||||
KEY_COLON: apply_to += ";"
|
||||
KEY_COMMA: apply_to += ","
|
||||
KEY_PERIOD: apply_to += "."
|
||||
KEY_MINUS: apply_to += "-"
|
||||
KEY_CAPSLOCK: return apply_to
|
||||
_: apply_to += OS.get_keycode_string(key).to_upper() if caps else OS.get_keycode_string(key).to_lower()
|
||||
|
||||
return apply_to
|
|
@ -20,32 +20,41 @@ signal on_key_up(event: EventKey)
|
|||
signal on_focus_in(event: EventFocus)
|
||||
signal on_focus_out(event: EventFocus)
|
||||
|
||||
var active_node: Node = null
|
||||
var _active_node: Node = null
|
||||
|
||||
func emit(type: String, event: Event):
|
||||
if event is EventBubble:
|
||||
_bubble_call(type, event.target, event)
|
||||
if event.target.is_in_group("ui_focus"):
|
||||
_handle_focus(event.target)
|
||||
else:
|
||||
_handle_focus(null)
|
||||
if type == "press_down":
|
||||
_handle_focus(event)
|
||||
else:
|
||||
_root_call(type, event)
|
||||
|
||||
func _handle_focus(node: Node):
|
||||
var event = EventFocus.new()
|
||||
event.previous_target = active_node
|
||||
event.target = node
|
||||
func is_focused(node: Node):
|
||||
return _active_node == node
|
||||
|
||||
if active_node != null && active_node.has_method(FN_PREFIX + "focus_in"):
|
||||
active_node.call(FN_PREFIX + "focus_out", event)
|
||||
on_focus_out.emit(event)
|
||||
func _handle_focus(event: EventRay):
|
||||
if event.target != null && event.target.is_in_group("ui_focus_skip"):
|
||||
return
|
||||
|
||||
active_node = node
|
||||
var event_focus = EventFocus.new()
|
||||
event_focus.previous_target = _active_node
|
||||
event_focus.target = event.target
|
||||
event_focus.ray = event.ray
|
||||
|
||||
if active_node != null:
|
||||
active_node.call(FN_PREFIX + "focus_in", event)
|
||||
on_focus_in.emit(event)
|
||||
if _active_node != null && _active_node.has_method(FN_PREFIX + "focus_out"):
|
||||
_active_node.call(FN_PREFIX + "focus_out", event_focus)
|
||||
on_focus_out.emit(event_focus)
|
||||
|
||||
if event.target == null || event.target.is_in_group("ui_focus") == false:
|
||||
_active_node = null
|
||||
return
|
||||
|
||||
_active_node = event.target
|
||||
|
||||
if _active_node != null && _active_node.has_method(FN_PREFIX + "focus_in"):
|
||||
_active_node.call(FN_PREFIX + "focus_in", event_focus)
|
||||
on_focus_in.emit(event_focus)
|
||||
|
||||
func _bubble_call(type: String, target: Variant, event: EventBubble):
|
||||
if target == null:
|
||||
|
|
Loading…
Reference in New Issue
Block a user