Merge pull request #53 from Nitwel/testing

Implement experimental handtracking
This commit is contained in:
Nitwel 2023-11-28 15:15:42 +01:00 committed by GitHub
commit 0c5cfba55f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 1246 additions and 291 deletions

1
.gitattributes vendored
View File

@ -10,6 +10,7 @@
*.tres filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.glb filter=lfs diff=lfs merge=lfs -text
*.gltf filter=lfs diff=lfs merge=lfs -text
*.obj filter=lfs diff=lfs merge=lfs -text
*.mtl filter=lfs diff=lfs merge=lfs -text

View File

@ -117,15 +117,15 @@ It is also possible to bubble up information by returning a dictionary from a fu
| Function called | Args | Description |
| -- | -- | -- |
| `_on_click` | `[event: EventRay]` | The back trigger button has been pressed and released |
| `_on_press_down` | `[event: EventRay]` | The back trigger button has been pressed down |
| `_on_press_move` | `[event: EventRay]` | The back trigger button has been moved while pressed down |
| `_on_press_up` | `[event: EventRay]` | The back trigger button has been released |
| `_on_grab_down` | `[event: EventRay]` | The side grab button been pressed down |
| `_on_grab_move` | `[event: EventRay]` | The side grab button been pressed down |
| `_on_grab_up` | `[event: EventRay]` | The side grab button been released |
| `_on_ray_enter` | `[event: EventRay]` | The ray-cast enters the the collision body |
| `_on_ray_leave` | `[event: EventRay]` | The ray-cast leaves the the collision body |
| `_on_click` | `[event: EventPointer]` | The back trigger button has been pressed and released |
| `_on_press_down` | `[event: EventPointer]` | The back trigger button has been pressed down |
| `_on_press_move` | `[event: EventPointer]` | The back trigger button has been moved while pressed down |
| `_on_press_up` | `[event: EventPointer]` | The back trigger button has been released |
| `_on_grab_down` | `[event: EventPointer]` | The side grab button been pressed down |
| `_on_grab_move` | `[event: EventPointer]` | The side grab button been pressed down |
| `_on_grab_up` | `[event: EventPointer]` | The side grab button been released |
| `_on_ray_enter` | `[event: EventPointer]` | The ray-cast enters the the collision body |
| `_on_ray_leave` | `[event: EventPointer]` | The ray-cast leaves the the collision body |
| `_on_key_down` | `[event: EventKey]` | The ray-cast leaves the the collision body |
| `_on_key_up` | `[event: EventKey]` | The ray-cast leaves the the collision body |
| `_on_focus_in` | `[event: EventFocus]` | The node is got focused |
@ -140,8 +140,9 @@ Thus I've decided to use a custom event system that is similar to the one used i
| Group | Description |
| -- | -- |
| `entity` | Marks the object as being an entity placed in space |
| `ui_focus` | The element can be focused |
| `ui_focus_skip` | The focus will not be reset. Useful for keyboard |
| `ui_focus` | The element can be focused, can be a parent |
| `ui_focus_skip` | Focus checking on this element will be skipped |
| `ui_focus_stop` | The focus will not be reset. Useful for keyboard |
### Functions

View File

@ -1,40 +1,40 @@
[gd_scene load_steps=13 format=3 uid="uid://njx823gyk04n"]
[ext_resource type="PackedScene" uid="uid://q1l3fknstir2" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_L.gltf" id="1"]
[ext_resource type="PackedScene" uid="uid://bh786yhm5v4fh" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_L.gltf" id="1"]
[ext_resource type="PackedScene" uid="uid://the6y7swe6j0" path="res://addons/godot-xr-tools/hands/animations/left/AnimationPlayer.tscn" id="2"]
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/hand.gd" id="3"]
[ext_resource type="Resource" uid="uid://dertgu7k8alls" path="res://addons/godot-xr-tools/hands/poses/pose_default_left.tres" id="3_k56uy"]
[ext_resource type="AnimationNodeBlendTree" uid="uid://dl8yf7ipqotd1" path="res://addons/godot-xr-tools/hands/animations/left/hand_blend_tree.tres" id="5"]
[ext_resource type="Material" uid="uid://dbvge3quu3bju" path="res://addons/godot-xr-tools/hands/materials/caucasian_hand.material" id="6"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_x12eo"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_e6byy"]
animation = &"Grip"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_kw2gg"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_bs8g1"]
animation = &"Grip"
[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_o8j0s"]
[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_675c4"]
filter_enabled = true
filters = ["Armature/Skeleton3D:Little_Distal_L", "Armature/Skeleton3D:Little_Intermediate_L", "Armature/Skeleton3D:Little_Metacarpal_L", "Armature/Skeleton3D:Little_Proximal_L", "Armature/Skeleton3D:Middle_Distal_L", "Armature/Skeleton3D:Middle_Intermediate_L", "Armature/Skeleton3D:Middle_Metacarpal_L", "Armature/Skeleton3D:Middle_Proximal_L", "Armature/Skeleton3D:Ring_Distal_L", "Armature/Skeleton3D:Ring_Intermediate_L", "Armature/Skeleton3D:Ring_Metacarpal_L", "Armature/Skeleton3D:Ring_Proximal_L", "Armature/Skeleton3D:Thumb_Distal_L", "Armature/Skeleton3D:Thumb_Metacarpal_L", "Armature/Skeleton3D:Thumb_Proximal_L", "Armature/Skeleton:Little_Distal_L", "Armature/Skeleton:Little_Intermediate_L", "Armature/Skeleton:Little_Proximal_L", "Armature/Skeleton:Middle_Distal_L", "Armature/Skeleton:Middle_Intermediate_L", "Armature/Skeleton:Middle_Proximal_L", "Armature/Skeleton:Ring_Distal_L", "Armature/Skeleton:Ring_Intermediate_L", "Armature/Skeleton:Ring_Proximal_L", "Armature/Skeleton:Thumb_Distal_L", "Armature/Skeleton:Thumb_Proximal_L"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_cxcnq"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_2ssci"]
animation = &"Grip 5"
[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_yn70n"]
[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_narw6"]
filter_enabled = true
filters = ["Armature/Skeleton3D:Index_Distal_L", "Armature/Skeleton3D:Index_Intermediate_L", "Armature/Skeleton3D:Index_Metacarpal_L", "Armature/Skeleton3D:Index_Proximal_L", "Armature/Skeleton:Index_Distal_L", "Armature/Skeleton:Index_Intermediate_L", "Armature/Skeleton:Index_Proximal_L"]
[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_v8owg"]
[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_wp4n0"]
graph_offset = Vector2(-536, 11)
nodes/ClosedHand1/node = SubResource("AnimationNodeAnimation_x12eo")
nodes/ClosedHand1/node = SubResource("AnimationNodeAnimation_e6byy")
nodes/ClosedHand1/position = Vector2(-600, 300)
nodes/ClosedHand2/node = SubResource("AnimationNodeAnimation_kw2gg")
nodes/ClosedHand2/node = SubResource("AnimationNodeAnimation_bs8g1")
nodes/ClosedHand2/position = Vector2(-360, 300)
nodes/Grip/node = SubResource("AnimationNodeBlend2_o8j0s")
nodes/Grip/node = SubResource("AnimationNodeBlend2_675c4")
nodes/Grip/position = Vector2(0, 20)
nodes/OpenHand/node = SubResource("AnimationNodeAnimation_cxcnq")
nodes/OpenHand/node = SubResource("AnimationNodeAnimation_2ssci")
nodes/OpenHand/position = Vector2(-600, 100)
nodes/Trigger/node = SubResource("AnimationNodeBlend2_yn70n")
nodes/Trigger/node = SubResource("AnimationNodeBlend2_narw6")
nodes/Trigger/position = Vector2(-360, 20)
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
@ -73,7 +73,7 @@ surface_material_override/0 = ExtResource("6")
[node name="AnimationPlayer" parent="Hand_Nails_L" instance=ExtResource("2")]
[node name="AnimationTree" type="AnimationTree" parent="."]
tree_root = SubResource("AnimationNodeBlendTree_v8owg")
tree_root = SubResource("AnimationNodeBlendTree_wp4n0")
anim_player = NodePath("../Hand_Nails_L/AnimationPlayer")
active = true
parameters/Grip/blend_amount = 0.0

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:86eced068bcbed2d727b107358398aff996d92dddedaeff7277430262507bcb1
size 233

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:26fbc4673b78bf69b4955cd131e2484f705d833528cb3040223434c8bec9fe18
size 92814

View File

@ -0,0 +1,21 @@
[remap]
importer="wavefront_obj"
importer_version=1
type="Mesh"
uid="uid://iv4lk77axlk4"
path="res://.godot/imported/button.obj-e6c969b54c5afbe601f3ea5c30bde0ec.mesh"
[deps]
files=["res://.godot/imported/button.obj-e6c969b54c5afbe601f3ea5c30bde0ec.mesh"]
source_file="res://assets/immersive_home/button.obj"
dest_files=["res://.godot/imported/button.obj-e6c969b54c5afbe601f3ea5c30bde0ec.mesh", "res://.godot/imported/button.obj-e6c969b54c5afbe601f3ea5c30bde0ec.mesh"]
[params]
generate_tangents=true
scale_mesh=Vector3(1, 1, 1)
offset_mesh=Vector3(0, 0, 0)
optimize_mesh=true

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:135189e6a2caab7d5fa0182feda4c2c7b1a9485bc5a7b27b0fe7b5b5ed7e33eb
size 40061376

View File

@ -0,0 +1,32 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://dt4ksvogfctkr"
path="res://.godot/imported/left_hand.glb-d1b6eb8d19651a395c75d8356aea3687.scn"
[deps]
source_file="res://assets/models/hands_steam/left_hand.glb"
dest_files=["res://.godot/imported/left_hand.glb-d1b6eb8d19651a395c75d8356aea3687.scn"]
[params]
nodes/root_type="Node3D"
nodes/root_name="Scene Root"
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/embedded_image_handling=1

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:285a2e53aa6d3054749ffcd965a193cb1ddfeedd0bde1f33c8e339eb3d6e077e
size 30680477

View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://y2l04213se8o"
path.s3tc="res://.godot/imported/left_hand_file2.png-753ecb3429d6d797b17376208f876be4.s3tc.ctex"
path.etc2="res://.godot/imported/left_hand_file2.png-753ecb3429d6d797b17376208f876be4.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
generator_parameters={}
[deps]
source_file="res://assets/models/hands_steam/left_hand_file2.png"
dest_files=["res://.godot/imported/left_hand_file2.png-753ecb3429d6d797b17376208f876be4.s3tc.ctex", "res://.godot/imported/left_hand_file2.png-753ecb3429d6d797b17376208f876be4.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=1
roughness/src_normal="res://left_hand_file2.png"
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d7877cf67239ad881c8c4fa5773b9f09d7f35ca763345163800d18e25a52253c
size 18391772

View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dmrf63au6a5jr"
path.s3tc="res://.godot/imported/left_hand_file3.png-88d88e1602347accb4d3c945bb045e57.s3tc.ctex"
path.etc2="res://.godot/imported/left_hand_file3.png-88d88e1602347accb4d3c945bb045e57.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
generator_parameters={}
[deps]
source_file="res://assets/models/hands_steam/left_hand_file3.png"
dest_files=["res://.godot/imported/left_hand_file3.png-88d88e1602347accb4d3c945bb045e57.s3tc.ctex", "res://.godot/imported/left_hand_file3.png-88d88e1602347accb4d3c945bb045e57.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:135189e6a2caab7d5fa0182feda4c2c7b1a9485bc5a7b27b0fe7b5b5ed7e33eb
size 40061376

View File

@ -0,0 +1,32 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://cxaoselwp17hj"
path="res://.godot/imported/openxr_glove_left_model_slim.glb-3bc08bf7e42d440cc1352baebd3824f3.scn"
[deps]
source_file="res://assets/models/hands_steam/openxr_glove_left_model_slim.glb"
dest_files=["res://.godot/imported/openxr_glove_left_model_slim.glb-3bc08bf7e42d440cc1352baebd3824f3.scn"]
[params]
nodes/root_type="Node3D"
nodes/root_name="Scene Root"
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/embedded_image_handling=1

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:285a2e53aa6d3054749ffcd965a193cb1ddfeedd0bde1f33c8e339eb3d6e077e
size 30680477

View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cqq4ir2g3dtts"
path.s3tc="res://.godot/imported/openxr_glove_left_model_slim_file2.png-b570006e307615a62ead358262b940b2.s3tc.ctex"
path.etc2="res://.godot/imported/openxr_glove_left_model_slim_file2.png-b570006e307615a62ead358262b940b2.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
generator_parameters={}
[deps]
source_file="res://assets/models/hands_steam/openxr_glove_left_model_slim_file2.png"
dest_files=["res://.godot/imported/openxr_glove_left_model_slim_file2.png-b570006e307615a62ead358262b940b2.s3tc.ctex", "res://.godot/imported/openxr_glove_left_model_slim_file2.png-b570006e307615a62ead358262b940b2.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=1
roughness/src_normal="res://hands/openxr_glove_left_model_slim_file2.png"
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d7877cf67239ad881c8c4fa5773b9f09d7f35ca763345163800d18e25a52253c
size 18391772

View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cjyf87dcd0me5"
path.s3tc="res://.godot/imported/openxr_glove_left_model_slim_file3.png-e75731c876f664216c04a5bf1e9c9169.s3tc.ctex"
path.etc2="res://.godot/imported/openxr_glove_left_model_slim_file3.png-e75731c876f664216c04a5bf1e9c9169.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
generator_parameters={}
[deps]
source_file="res://assets/models/hands_steam/openxr_glove_left_model_slim_file3.png"
dest_files=["res://.godot/imported/openxr_glove_left_model_slim_file3.png-e75731c876f664216c04a5bf1e9c9169.s3tc.ctex", "res://.godot/imported/openxr_glove_left_model_slim_file3.png-e75731c876f664216c04a5bf1e9c9169.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d7d207229f1878c83742db31a111de44f7cf3136d03a3e7bf1f9c786bc30d550
size 40061252

View File

@ -0,0 +1,32 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://c0kow4g10wolq"
path="res://.godot/imported/right_hand.glb-499944075af999d8767516b6c91d6fd4.scn"
[deps]
source_file="res://assets/models/hands_steam/right_hand.glb"
dest_files=["res://.godot/imported/right_hand.glb-499944075af999d8767516b6c91d6fd4.scn"]
[params]
nodes/root_type="Node3D"
nodes/root_name="Scene Root"
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={}
gltf/embedded_image_handling=1

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:285a2e53aa6d3054749ffcd965a193cb1ddfeedd0bde1f33c8e339eb3d6e077e
size 30680477

View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://evlov5fjs1p8"
path.s3tc="res://.godot/imported/right_hand_file2.png-9b7fb1444ba3b2f541b7b4585d90cdef.s3tc.ctex"
path.etc2="res://.godot/imported/right_hand_file2.png-9b7fb1444ba3b2f541b7b4585d90cdef.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
generator_parameters={}
[deps]
source_file="res://assets/models/hands_steam/right_hand_file2.png"
dest_files=["res://.godot/imported/right_hand_file2.png-9b7fb1444ba3b2f541b7b4585d90cdef.s3tc.ctex", "res://.godot/imported/right_hand_file2.png-9b7fb1444ba3b2f541b7b4585d90cdef.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=1
roughness/src_normal="res://hands/right_hand_file2.png"
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d7877cf67239ad881c8c4fa5773b9f09d7f35ca763345163800d18e25a52253c
size 18391772

View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cydfo11uxp7yl"
path.s3tc="res://.godot/imported/right_hand_file3.png-b171de262cdca817d47ed129181b9a5c.s3tc.ctex"
path.etc2="res://.godot/imported/right_hand_file3.png-b171de262cdca817d47ed129181b9a5c.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
generator_parameters={}
[deps]
source_file="res://assets/models/hands_steam/right_hand_file3.png"
dest_files=["res://.godot/imported/right_hand_file3.png-b171de262cdca817d47ed129181b9a5c.s3tc.ctex", "res://.godot/imported/right_hand_file3.png-b171de262cdca817d47ed129181b9a5c.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

View File

@ -91,6 +91,7 @@ bottom_radius = 0.006
height = 0.004
[node name="Light" type="StaticBody3D" groups=["entity"]]
collision_mask = 0
script = ExtResource("1_ykxy3")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
@ -127,6 +128,7 @@ libraries = {
[node name="Rod" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.0903599)
collision_mask = 0
[node name="MeshInstance3D" type="MeshInstance3D" parent="Rod"]
mesh = SubResource("CylinderMesh_j3pn3")

View File

@ -8,6 +8,7 @@
size = Vector3(0.23, 0.142768, 0.01)
[node name="MediaPlayer" type="StaticBody3D" groups=["entity"]]
collision_mask = 0
script = ExtResource("1_ame17")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]

View File

@ -7,6 +7,7 @@
radius = 0.1
[node name="Sensor" type="StaticBody3D" groups=["entity"]]
collision_mask = 0
script = ExtResource("1_57ac8")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]

View File

@ -1,8 +1,8 @@
[gd_scene load_steps=7 format=3 uid="uid://cscl5k7lhopj5"]
[ext_resource type="Script" path="res://content/entities/switch/switch.gd" id="1_8ffhi"]
[ext_resource type="Texture2D" uid="uid://b72vsbcvqqxg7" path="res://assets/materials/swich_on.png" id="1_w68gw"]
[ext_resource type="Texture2D" uid="uid://cvc0o6dsktnvl" path="res://assets/materials/switch_off.png" id="2_86ba1"]
[ext_resource type="Texture2D" uid="uid://br3p0c2foputg" path="res://assets/materials/swich_on.png" id="1_w68gw"]
[ext_resource type="Texture2D" uid="uid://co2ishj2hx57p" path="res://assets/materials/switch_off.png" id="2_86ba1"]
[ext_resource type="Script" path="res://content/functions/movable.gd" id="4_6xr03"]
[sub_resource type="SphereShape3D" id="SphereShape3D_ukj14"]
@ -23,6 +23,7 @@ animations = [{
}]
[node name="Switch" type="StaticBody3D" groups=["entity"]]
collision_mask = 0
script = ExtResource("1_8ffhi")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]

View File

@ -1,39 +1,39 @@
extends Function
class_name Clickable
signal on_click(event: EventRay)
signal on_press_down(event: EventRay)
signal on_press_move(event: EventRay)
signal on_press_up(event: EventRay)
signal on_grab_down(event: EventRay)
signal on_grab_move(event: EventRay)
signal on_grab_up(event: EventRay)
signal on_ray_enter(event: EventRay)
signal on_ray_leave(event: EventRay)
signal on_click(event: EventPointer)
signal on_press_down(event: EventPointer)
signal on_press_move(event: EventPointer)
signal on_press_up(event: EventPointer)
signal on_grab_down(event: EventPointer)
signal on_grab_move(event: EventPointer)
signal on_grab_up(event: EventPointer)
signal on_ray_enter(event: EventPointer)
signal on_ray_leave(event: EventPointer)
func _on_click(event: EventRay):
func _on_click(event: EventPointer):
on_click.emit(event)
func _on_press_down(event: EventRay):
func _on_press_down(event: EventPointer):
on_press_down.emit(event)
func _on_press_move(event: EventRay):
func _on_press_move(event: EventPointer):
on_press_move.emit(event)
func _on_press_up(event: EventRay):
func _on_press_up(event: EventPointer):
on_press_up.emit(event)
func _on_grab_down(event: EventRay):
func _on_grab_down(event: EventPointer):
on_grab_down.emit(event)
func _on_grab_move(event: EventRay):
func _on_grab_move(event: EventPointer):
on_grab_move.emit(event)
func _on_grab_up(event: EventRay):
func _on_grab_up(event: EventPointer):
on_grab_up.emit(event)
func _on_ray_enter(event: EventRay):
func _on_ray_enter(event: EventPointer):
on_ray_enter.emit(event)
func _on_ray_leave(event: EventRay):
func _on_ray_leave(event: EventPointer):
on_ray_leave.emit(event)

View File

@ -4,15 +4,15 @@ class_name Movable
var hit_node := Node3D.new()
func _on_grab_down(event: EventRay):
event.controller.add_child(hit_node)
func _on_grab_down(event: EventPointer):
event.initiator.node.add_child(hit_node)
hit_node.global_transform = get_parent().global_transform
func _on_grab_move(_event: EventRay):
func _on_grab_move(_event: EventPointer):
get_parent().global_transform = hit_node.global_transform
func _on_grab_up(event: EventRay):
event.controller.remove_child(hit_node)
func _on_grab_up(event: EventPointer):
event.initiator.node.remove_child(hit_node)
func _get_configuration_warnings() -> PackedStringArray:
var warnings := PackedStringArray()

View File

@ -1,9 +1,10 @@
[gd_scene load_steps=13 format=3 uid="uid://eecv28y6jxk4"]
[gd_scene load_steps=14 format=3 uid="uid://eecv28y6jxk4"]
[ext_resource type="PackedScene" uid="uid://clc5dre31iskm" path="res://addons/godot-xr-tools/xr/start_xr.tscn" id="1_i4c04"]
[ext_resource type="Script" path="res://content/main.gd" id="1_uvrd4"]
[ext_resource type="PackedScene" uid="uid://b30w6tywfj4fp" path="res://content/system/controller_left/controller_left.tscn" id="2_2lraw"]
[ext_resource type="PackedScene" uid="uid://d3f8glx1xgm5w" path="res://content/system/raycast/raycast.tscn" id="3_67lii"]
[ext_resource type="PackedScene" uid="uid://bsx12q23v8apy" path="res://content/system/hands/hands.tscn" id="4_v8xu6"]
[ext_resource type="PackedScene" uid="uid://ctltchlf2j2r4" path="res://addons/xr-simulator/XRSimulator.tscn" id="5_3qc8g"]
[ext_resource type="Material" uid="uid://bf5ina366dwm6" path="res://assets/materials/sky.material" id="5_wgwf8"]
[ext_resource type="PackedScene" uid="uid://83lb5p4e0qk0" path="res://content/scenes/house.tscn" id="8_qkrg7"]
@ -50,6 +51,11 @@ mesh = SubResource("BoxMesh_ir3co")
[node name="Raycast" parent="XROrigin3D/XRControllerRight" instance=ExtResource("3_67lii")]
[node name="Hands" parent="XROrigin3D" node_paths=PackedStringArray("ray_left", "ray_right") instance=ExtResource("4_v8xu6")]
transform = Transform3D(0.999968, -1.39576e-11, 0, 9.52038e-12, 0.999984, -2.59206e-11, -2.91038e-11, 5.22959e-11, 0.999984, 0, 0, 0)
ray_left = NodePath("../XRControllerLeft/Raycast")
ray_right = NodePath("../XRControllerRight/Raycast")
[node name="StartXR" parent="." instance=ExtResource("1_i4c04")]
enable_passthrough = true
@ -69,3 +75,5 @@ visible = false
[node name="Keyboard" parent="." instance=ExtResource("9_e5n3p")]
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)
[editable path="XROrigin3D/XRControllerLeft"]

View File

@ -34,7 +34,7 @@ var trash_bin_large: bool = false:
func _ready():
trash_bin_visible = false
EventSystem.on_grab_down.connect(func(event: EventRay):
EventSystem.on_grab_down.connect(func(event: EventPointer):
trash_bin_visible = event.target.is_in_group("entity")
)
@ -53,7 +53,7 @@ func _ready():
)
EventSystem.on_grab_up.connect(func(_event: EventRay):
EventSystem.on_grab_up.connect(func(_event: EventPointer):
if !trash_bin_visible:
return

View File

@ -2,7 +2,7 @@
[ext_resource type="Script" path="res://content/system/controller_left/controller_left.gd" id="1_2j3qs"]
[ext_resource type="PackedScene" uid="uid://c3kdssrmv84kv" path="res://content/ui/menu/menu.tscn" id="1_ccbr3"]
[ext_resource type="PackedScene" uid="uid://cj42our8uhfq6" path="res://assets/models/trash_bin/trash_bin.gltf" id="3_m33ce"]
[ext_resource type="PackedScene" uid="uid://dqjcqdhe3rbtn" path="res://assets/models/trash_bin/trash_bin.gltf" id="3_m33ce"]
[ext_resource type="PackedScene" uid="uid://d3f8glx1xgm5w" path="res://content/system/raycast/raycast.tscn" id="4_n7lao"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"]
@ -111,6 +111,7 @@ transform = Transform3D(0.03, 0, 0, 0, 0.03, 0, 0, 0, 0.03, 0.106903, -0.228617,
[node name="Area3D" type="Area3D" parent="trash_bin"]
transform = Transform3D(25, 0, 0, 0, 25, 0, 0, 0, 25, 0, 0, 0)
collision_layer = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="trash_bin/Area3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0542412, 0)

View File

@ -0,0 +1,106 @@
extends Node3D
const Pointer = preload("res://lib/utils/pointer/pointer.gd")
const Initiator = preload("res://lib/utils/pointer/initiator.gd")
const Finger = preload("res://lib/utils/touch/finger.gd")
const Touch = preload("res://lib/utils/touch/touch.gd")
@onready var hand_right: OpenXRHand = $XRHandRight
@onready var hand_left: OpenXRHand = $XRHandLeft
@export var ray_left: RayCast3D
@export var ray_right: RayCast3D
var initiator: Initiator = Initiator.new()
var touch: Touch
var pointer: Pointer
var press_distance = 0.03
var grip_distance = 0.03
var close_distance = 0.1
var pressed_left = false
var pressed_right = false
var grabbed_left = false
var grabbed_right = false
func _ready():
touch = Touch.new({
Finger.Type.INDEX_RIGHT: $XRHandRight/IndexTip/TouchArea,
Finger.Type.INDEX_LEFT: $XRHandLeft/IndexTip/TouchArea,
Finger.Type.MIDDLE_RIGHT: $XRHandRight/MiddleTip/TouchArea,
Finger.Type.MIDDLE_LEFT: $XRHandLeft/MiddleTip/TouchArea
})
add_child(touch)
_ready_hand(hand_right)
func _ready_hand(hand: OpenXRHand):
initiator.type = Initiator.Type.HAND_RIGHT if hand == hand_right else Initiator.Type.HAND_LEFT
initiator.node = ray_left.get_parent() if hand == hand_left else ray_right.get_parent()
pointer = Pointer.new(initiator, ray_left if hand == hand_left else ray_right)
add_child(pointer)
func _process(_delta):
_process_hand(hand_right)
func _process_hand(hand: OpenXRHand):
var index_tip = hand.get_node("IndexTip/Marker3D")
var thumb_tip = hand.get_node("ThumbTip/Marker3D")
var middle_tip = hand.get_node("MiddleTip/Marker3D")
var _ray = ray_left if hand == hand_left else ray_right
var distance_trigger = index_tip.global_position.distance_to(thumb_tip.global_position)
var distance_grab = middle_tip.global_position.distance_to(thumb_tip.global_position)
var distance_target = _ray.get_collision_point().distance_to(_ray.global_position)
var trigger_close = distance_trigger <= press_distance
var grab_close = distance_grab <= grip_distance
var distance_close = distance_target <= close_distance
if hand == hand_left:
if !distance_close:
if trigger_close && !pressed_left:
initiator.on_press.emit(Initiator.EventType.TRIGGER)
pressed_left = true
elif !trigger_close && pressed_left:
initiator.on_release.emit(Initiator.EventType.TRIGGER)
pressed_left = false
if grab_close && !grabbed_left:
initiator.on_press.emit(Initiator.EventType.GRIP)
grabbed_left = true
elif !grab_close && grabbed_left:
initiator.on_release.emit(Initiator.EventType.GRIP)
grabbed_left = false
else:
if trigger_close && !grabbed_right:
initiator.on_press.emit(Initiator.EventType.GRIP)
grabbed_right = true
elif !trigger_close && grabbed_right:
initiator.on_release.emit(Initiator.EventType.GRIP)
grabbed_right = false
else:
if !distance_close:
if trigger_close && !pressed_right:
initiator.on_press.emit(Initiator.EventType.TRIGGER)
pressed_right = true
elif !trigger_close && pressed_right:
initiator.on_release.emit(Initiator.EventType.TRIGGER)
pressed_right = false
if grab_close && !grabbed_right:
initiator.on_press.emit(Initiator.EventType.GRIP)
grabbed_right = true
elif !grab_close && grabbed_right:
initiator.on_release.emit(Initiator.EventType.GRIP)
grabbed_right = false
else:
if trigger_close && !grabbed_right:
initiator.on_press.emit(Initiator.EventType.GRIP)
grabbed_right = true
elif !trigger_close && grabbed_right:
initiator.on_release.emit(Initiator.EventType.GRIP)
grabbed_right = false

View File

@ -0,0 +1,160 @@
[gd_scene load_steps=6 format=3 uid="uid://bsx12q23v8apy"]
[ext_resource type="Script" path="res://content/system/hands/hands.gd" id="1_c4f76"]
[ext_resource type="PackedScene" uid="uid://c0kow4g10wolq" path="res://assets/models/hands_steam/right_hand.glb" id="1_uekbj"]
[ext_resource type="PackedScene" uid="uid://dt4ksvogfctkr" path="res://assets/models/hands_steam/left_hand.glb" id="2_n73lt"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_dopke"]
radius = 0.001
height = 0.02
[sub_resource type="BoxShape3D" id="BoxShape3D_1pxrt"]
size = Vector3(0.14, 0.0577792, 0.169383)
[node name="Hands" type="Node3D"]
script = ExtResource("1_c4f76")
[node name="XRHandLeft" type="OpenXRHand" parent="."]
transform = Transform3D(0.999999, -1.39628e-11, 0, 9.48119e-12, 0.999999, -4.54747e-13, 0, 0, 0.999999, -0.25, 0, 0)
hand_skeleton = NodePath("left_hand/Armature_001/Skeleton3D")
[node name="left_hand" parent="XRHandLeft" instance=ExtResource("2_n73lt")]
transform = Transform3D(1, 4.42441e-11, 0, -1.06936e-10, 1, 1.81899e-12, 5.82077e-11, -1.81899e-12, 1, 0, 0, 0.033)
[node name="IndexTip" type="BoneAttachment3D" parent="XRHandLeft"]
transform = Transform3D(0.19221, -0.669965, -0.717079, 0.977075, 0.19881, 0.076153, 0.0915428, -0.715277, 0.692819, 0.0345973, 0.0355402, -0.131767)
bone_name = "Index_Tip_L"
bone_idx = 9
use_external_skeleton = true
external_skeleton = NodePath("../left_hand/Armature_001/Skeleton3D")
[node name="Marker3D" type="Marker3D" parent="XRHandLeft/IndexTip"]
gizmo_extents = 0.02
[node name="TouchArea" type="Area3D" parent="XRHandLeft/IndexTip"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0.01)
collision_layer = 0
collision_mask = 4
monitorable = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="XRHandLeft/IndexTip/TouchArea"]
transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0, 1, 0, 0, 0)
shape = SubResource("CapsuleShape3D_dopke")
[node name="ThumbTip" type="BoneAttachment3D" parent="XRHandLeft"]
transform = Transform3D(0.937246, 0.0284254, -0.347508, 0.0184905, 0.991216, 0.130949, 0.348178, -0.129157, 0.928488, 0.0498668, 0.0560917, -0.0797768)
bone_name = "Thumb_Tip_L"
bone_idx = 4
use_external_skeleton = true
external_skeleton = NodePath("../left_hand/Armature_001/Skeleton3D")
[node name="Marker3D" type="Marker3D" parent="XRHandLeft/ThumbTip"]
gizmo_extents = 0.02
[node name="MiddleTip" type="BoneAttachment3D" parent="XRHandLeft"]
transform = Transform3D(0.0812012, -0.650531, -0.755125, 0.996577, 0.064817, 0.051326, 0.0155558, -0.756708, 0.653568, 0.032112, 0.00654224, -0.138612)
bone_name = "Middle_Tip_L"
bone_idx = 14
use_external_skeleton = true
external_skeleton = NodePath("../left_hand/Armature_001/Skeleton3D")
[node name="Marker3D" type="Marker3D" parent="XRHandLeft/MiddleTip"]
gizmo_extents = 0.02
[node name="TouchArea" type="Area3D" parent="XRHandLeft/MiddleTip"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0.01)
collision_layer = 0
collision_mask = 4
monitorable = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="XRHandLeft/MiddleTip/TouchArea"]
transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0, 1, 0, 0, 0)
shape = SubResource("CapsuleShape3D_dopke")
[node name="AnimatableBody3D" type="AnimatableBody3D" parent="XRHandLeft"]
transform = Transform3D(1, 8.67362e-19, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)
collision_layer = 8
collision_mask = 8
[node name="CollisionShape3D" type="CollisionShape3D" parent="XRHandLeft/AnimatableBody3D"]
transform = Transform3D(1, 8.67362e-19, 4.75779e-13, -2.32831e-10, 1, -1.77636e-14, -4.97946e-12, 1.77636e-15, 1, -7.7486e-07, 1.33878e-09, -0.030436)
shape = SubResource("BoxShape3D_1pxrt")
[node name="RemoteTransform3D" type="RemoteTransform3D" parent="XRHandLeft"]
remote_path = NodePath("../AnimatableBody3D")
[node name="XRHandRight" type="OpenXRHand" parent="."]
transform = Transform3D(0.999998, -0.000567105, -2.5179e-05, -2.51789e-05, 4.39886e-08, -0.999999, 0.000567104, 0.999999, 2.97064e-08, 0.264391, 0, 0)
hand = 1
hand_skeleton = NodePath("right_hand/Armature/Skeleton3D")
[node name="right_hand" parent="XRHandRight" instance=ExtResource("1_uekbj")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.033)
[node name="vr_glove_right_slim" parent="XRHandRight/right_hand/Armature/Skeleton3D" index="0"]
transform = Transform3D(1, 0, 4.7579e-13, 0, 1, 0, -1.34149e-12, 1.77636e-15, 1, 0, 0, 0)
[node name="IndexTip" type="BoneAttachment3D" parent="XRHandRight"]
transform = Transform3D(0.19221, 0.669966, 0.717079, -0.091543, -0.715277, 0.69282, 0.977075, -0.19881, -0.0761527, -0.0345977, -0.164767, -0.00254008)
bone_name = "Index_Tip_R"
bone_idx = 9
use_external_skeleton = true
external_skeleton = NodePath("../right_hand/Armature/Skeleton3D")
[node name="Marker3D" type="Marker3D" parent="XRHandRight/IndexTip"]
gizmo_extents = 0.02
[node name="TouchArea" type="Area3D" parent="XRHandRight/IndexTip"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0.01)
collision_layer = 0
collision_mask = 4
monitorable = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="XRHandRight/IndexTip/TouchArea"]
transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0, 1, 0, 0, 0)
shape = SubResource("CapsuleShape3D_dopke")
[node name="ThumbTip" type="BoneAttachment3D" parent="XRHandRight"]
transform = Transform3D(0.937246, -0.0284254, 0.347508, -0.348179, -0.129158, 0.928488, 0.0184906, -0.991216, -0.130949, -0.0498677, -0.112777, -0.0230909)
bone_name = "Thumb_Tip_R"
bone_idx = 4
use_external_skeleton = true
external_skeleton = NodePath("../right_hand/Armature/Skeleton3D")
[node name="Marker3D" type="Marker3D" parent="XRHandRight/ThumbTip"]
gizmo_extents = 0.02
[node name="MiddleTip" type="BoneAttachment3D" parent="XRHandRight"]
transform = Transform3D(0.0812011, 0.650531, 0.755126, -0.0155557, -0.756708, 0.653568, 0.996576, -0.0648169, -0.0513262, -0.032112, -0.171612, 0.0264578)
bone_name = "Middle_Tip_R"
bone_idx = 14
use_external_skeleton = true
external_skeleton = NodePath("../right_hand/Armature/Skeleton3D")
[node name="Marker3D" type="Marker3D" parent="XRHandRight/MiddleTip"]
gizmo_extents = 0.02
[node name="TouchArea" type="Area3D" parent="XRHandRight/MiddleTip"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0.01)
collision_layer = 0
collision_mask = 4
monitorable = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="XRHandRight/MiddleTip/TouchArea"]
transform = Transform3D(1, -7.45058e-09, -2.22045e-16, 7.45058e-09, 1, 0, 0, 0, 1, 0, 0, 0)
shape = SubResource("CapsuleShape3D_dopke")
[node name="AnimatableBody3D" type="AnimatableBody3D" parent="XRHandRight"]
transform = Transform3D(1, 0, 4.7579e-13, -5.82077e-11, 1, 0, -4.97947e-12, 1.77636e-15, 1, 0, 0, 0)
collision_layer = 8
collision_mask = 8
[node name="CollisionShape3D" type="CollisionShape3D" parent="XRHandRight/AnimatableBody3D"]
transform = Transform3D(1, 0, 4.75779e-13, -2.32831e-10, 1, -1.77636e-14, -4.97946e-12, 1.77636e-15, 1, -7.7486e-07, 1.33878e-09, -0.030436)
shape = SubResource("BoxShape3D_1pxrt")
[node name="RemoteTransform3D" type="RemoteTransform3D" parent="XRHandRight"]
remote_path = NodePath("../AnimatableBody3D")
[editable path="XRHandLeft/left_hand"]
[editable path="XRHandRight/right_hand"]

View File

@ -71,19 +71,18 @@ func create_key(key: Key):
var key_node = button_scene.instantiate()
key_node.label = EventKey.key_to_string(key, caps)
key_node.add_to_group("ui_focus_skip")
key_node.get_node("Label").font_size = 32
key_node.focusable = false
key_node.font_size = 32
key_node.set_meta("key", key)
return key_node
func update_labels():
for key_button in keys.get_children():
var label = key_button.get_children()[key_button.get_children().size() - 1]
if caps:
label.text = label.text.to_upper()
key_button.label = key_button.label.to_upper()
else:
label.text = label.text.to_lower()
key_button.label = key_button.label.to_lower()
func _emit_event(type: String, key: Key):
var event = EventKey.new()

View File

@ -11,24 +11,29 @@ size = Vector3(0.79, 0.01, 0.26)
[sub_resource type="BoxMesh" id="BoxMesh_7rntc"]
size = Vector3(0.79, 0.01, 0.26)
[node name="Keyboard" type="StaticBody3D" groups=["ui_focus_skip"]]
[node name="Keyboard" type="StaticBody3D" groups=["ui_focus_stop"]]
transform = Transform3D(0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0, 0, 0)
collision_layer = 2
collision_mask = 2
script = ExtResource("1_maojw")
[node name="Backspace" parent="." groups=["ui_focus_skip"] instance=ExtResource("1_xdpwr")]
[node name="Backspace" parent="." instance=ExtResource("1_xdpwr")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.66, 0, 0.02)
focusable = false
label = "backspace"
icon = true
metadata/key = 4194308
[node name="Caps" parent="." groups=["ui_focus_skip"] instance=ExtResource("1_xdpwr")]
[node name="Caps" parent="." instance=ExtResource("1_xdpwr")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.06, 0, 0.15)
focusable = false
label = "keyboard_capslock"
icon = true
toggleable = true
[node name="Paste" parent="." groups=["ui_focus_skip"] instance=ExtResource("1_xdpwr")]
[node name="Paste" parent="." instance=ExtResource("1_xdpwr")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.66, 0, 0.18)
focusable = false
label = "assignment"
icon = true

View File

@ -1,31 +1,40 @@
extends RayCast3D
const Pointer = preload("res://lib/utils/pointer/pointer.gd")
const Initiator = preload("res://lib/utils/pointer/initiator.gd")
@onready var cursor: Node3D = $Cursor
@onready var decal: Decal = $Decal
@export var is_right: bool = true
@export var with_decal: bool = false
var controller: XRController3D
var timespan_click = 200.0
@onready var pointer: Pointer
var last_collided: Object = null
var is_pressed := false
var is_grabbed := false
var time_pressed := 0.0
var moved := false
var click_point := Vector3.ZERO
var _event_type_map = {
"trigger_click": Initiator.EventType.TRIGGER,
"grip_click": Initiator.EventType.GRIP,
}
func _ready():
controller = get_parent()
assert(controller is XRController3D, "XRController3D is not found in parent")
var initiator = Initiator.new()
initiator.type = Initiator.Type.CONTROLLER_RIGHT if is_right else Initiator.Type.CONTROLLER_LEFT
initiator.node = get_parent()
assert(get_parent() is XRController3D, "Parent must be XRController3D")
controller.button_pressed.connect(_on_button_pressed)
controller.button_released.connect(_on_button_released)
pointer = Pointer.new(initiator, self)
add_child(pointer)
get_parent().button_pressed.connect(func(button: String):
if _event_type_map.has(button):
initiator.on_press.emit(_event_type_map[button])
)
get_parent().button_released.connect(func(button: String):
if _event_type_map.has(button):
initiator.on_release.emit(_event_type_map[button])
)
func _physics_process(_delta):
_handle_enter_leave()
_handle_move()
_handle_cursor()
func _handle_cursor():
@ -40,75 +49,3 @@ func _handle_cursor():
decal.visible = false
cursor.global_transform.origin = get_collision_point() + get_collision_normal() * 0.001 # offset to avoid z-fighting
cursor.global_transform.basis = Basis.looking_at(get_collision_normal(), Vector3.UP)
func _handle_move():
var time_passed = Time.get_ticks_msec() - time_pressed
if time_passed <= timespan_click || (is_pressed == false && is_grabbed == false):
return
moved = true
# reset if last_collided gets deleted
if is_instance_valid(last_collided) == false:
last_collided = null
return
if is_pressed:
_emit_event("press_move", last_collided )
if is_grabbed:
_emit_event("grab_move", last_collided )
func _handle_enter_leave():
var collider = get_collider()
if collider == last_collided || is_grabbed || is_pressed:
return
_emit_event("ray_enter", collider )
_emit_event("ray_leave", last_collided )
last_collided = collider
func _on_button_pressed(button: String):
var collider = get_collider()
if collider == null:
return
match button:
"trigger_click":
is_pressed = true
time_pressed = Time.get_ticks_msec()
click_point = get_collision_point()
_emit_event("press_down", collider )
"grip_click":
is_grabbed = true
click_point = get_collision_point()
_emit_event("grab_down", collider )
func _on_button_released(button: String):
match button:
"trigger_click":
if is_pressed:
if moved == false:
_emit_event("click", last_collided )
_emit_event("press_up", last_collided )
is_pressed = false
last_collided = null
moved = false
"grip_click":
if is_grabbed:
_emit_event("grab_up", last_collided )
is_grabbed = false
last_collided = null
moved = false
func _emit_event(type: String, target):
var event = EventRay.new()
event.controller = controller
event.target = target
event.ray = self
event.is_right_controller = is_right
EventSystem.emit(type, event)

View File

@ -6,6 +6,7 @@
[node name="Raycast" type="RayCast3D"]
transform = Transform3D(0.999999, -1.39624e-11, 0, 9.48108e-12, 0.999999, 0, 0, 4.54747e-13, 0.999998, -0.000467122, 0.00228411, -0.0016689)
target_position = Vector3(0, 0, -5)
collision_mask = 19
script = ExtResource("1_gp8nv")
[node name="Decal" type="Decal" parent="."]
@ -18,6 +19,6 @@ lower_fade = 0.000919435
[node name="Cursor" type="Node3D" parent="."]
[node name="CursorSprite" type="Sprite3D" parent="Cursor"]
transform = Transform3D(0.03, 3.25261e-20, -2.20405e-39, -3.25261e-20, 0.03, -2.03288e-21, 0, 2.03288e-21, 0.03, 0, 0, 0)
transform = Transform3D(0.03, 2.71051e-20, 0, -5.42101e-20, 0.03, -2.03288e-21, -2.46521e-33, 2.5411e-21, 0.03, 0, 0, 0)
pixel_size = 0.001
texture = ExtResource("1_2f2iv")

View File

@ -1,15 +1,31 @@
@tool
extends StaticBody3D
extends Node3D
class_name Button3D
const Proxy = preload("res://lib/utils/proxy.gd")
signal on_button_down()
signal on_button_up()
const IconFont = preload("res://assets/icons/icons.tres")
@onready var label_node: Label3D = $Label
@onready var label_node: Label3D = $Body/Label
@onready var finger_area: Area3D = $FingerArea
@export var focusable: bool = true:
set(value):
focusable = value
if value == false:
add_to_group("ui_focus_stop")
else:
remove_from_group("ui_focus_stop")
@export var font_size: int = 10:
set(value):
font_size = value
if !is_node_ready(): await ready
label_node.font_size = value
@export var label: String = "":
set(value):
label = value
@ -25,24 +41,27 @@ const IconFont = preload("res://assets/icons/icons.tres")
label_node.font_size = 48
label_node.width = 1000
label_node.autowrap_mode = TextServer.AUTOWRAP_OFF
else:
label_node.font = null
label_node.font_size = font_size
label_node.width = 50
label_node.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
@export var toggleable: bool = false
@export var disabled: bool = false
@export var external_state: bool = false
@export var initial_active: bool = false
var external_value: Proxy = null
var active: bool = false:
get:
if external_value != null:
return external_value.value
return active
set(value):
animation_player.stop()
if value == active:
return
active = value
if active:
animation_player.play("down")
if external_value != null:
external_value.value = value
else:
animation_player.play_backwards("down")
active = value
update_animation()
@onready var animation_player: AnimationPlayer = $AnimationPlayer
@ -50,6 +69,14 @@ func _ready():
if initial_active:
active = true
func update_animation():
var length = animation_player.get_animation("down").length
if active && animation_player.current_animation_position != length:
animation_player.play("down")
elif !active && animation_player.current_animation_position != 0:
animation_player.play_backwards("down")
func _on_press_down(event):
if disabled:
event.bubbling = false
@ -57,22 +84,17 @@ func _on_press_down(event):
AudioPlayer.play_effect("click")
if external_state || toggleable:
if toggleable:
return
active = true
on_button_down.emit()
func _on_press_up(event):
if disabled:
event.bubbling = false
return
if external_state:
return
if toggleable:
active = !active
@ -83,3 +105,54 @@ func _on_press_up(event):
else:
active = false
on_button_up.emit()
func _on_touch_enter(event: EventTouch):
animation_player.stop()
animation_player.speed_scale = 0
animation_player.current_animation = "down"
AudioPlayer.play_effect("click")
_touch_change(event)
func _on_touch_move(event: EventTouch):
_touch_change(event)
func _on_touch_leave(_event: EventTouch):
animation_player.stop()
animation_player.speed_scale = 1
if toggleable:
active = !active
if active:
on_button_up.emit()
else:
on_button_down.emit()
func _touch_change(event: EventTouch):
if disabled:
event.bubbling = false
return
var pos = Vector3(0, 1, 0)
for finger in event.fingers:
var finger_pos = to_local(finger.area.global_position)
if pos.y > finger_pos.y:
pos = finger_pos
var button_height = finger_area.get_node("CollisionShape3D").shape.size.y
var button_center = finger_area.position.y
var percent = clamp((button_center + button_height / 2 - pos.y) / (button_height / 2), 0, 1)
if !active && percent < 1:
on_button_down.emit()
elif active && percent >= 1:
on_button_up.emit()
animation_player.seek(percent * animation_player.current_animation_length, true)
if toggleable:
return
active = percent < 1

View File

@ -1,12 +1,11 @@
[gd_scene load_steps=8 format=3 uid="uid://bsjqdvkt0u87c"]
[gd_scene load_steps=9 format=3 uid="uid://bsjqdvkt0u87c"]
[ext_resource type="Script" path="res://content/ui/components/button/button.gd" id="1_74x7g"]
[ext_resource type="Material" uid="uid://bujy3egn1oqac" path="res://assets/materials/ui_element.material" id="2_h7ln4"]
[ext_resource type="ArrayMesh" uid="uid://iv4lk77axlk4" path="res://assets/immersive_home/button.obj" id="2_cve3l"]
[sub_resource type="BoxMesh" id="BoxMesh_jwpm5"]
resource_local_to_scene = true
material = ExtResource("2_h7ln4")
size = Vector3(0.05, 0.02, 0.05)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_8s8ln"]
transparency = 1
albedo_color = Color(0, 0.501961, 0.886275, 1)
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_o4j7g"]
points = PackedVector3Array(-0.025, -0.01, -0.025, -0.025, 0.01, -0.025, 0.025, -0.01, -0.025, -0.025, -0.01, 0.025, -0.025, 0.01, 0.025, 0.025, 0.01, -0.025, 0.025, -0.01, 0.025, 0.025, 0.01, 0.025)
@ -16,60 +15,50 @@ length = 0.001
tracks/0/type = "bezier"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:position:y")
tracks/0/path = NodePath("Body:scale:y")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0),
"points": PackedFloat32Array(1, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
tracks/1/type = "bezier"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("MeshInstance3D:position:y")
tracks/1/path = NodePath("Body:position:y")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0),
"points": PackedFloat32Array(0.01, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
[sub_resource type="Animation" id="Animation_iu2ed"]
resource_name = "down"
length = 0.2
step = 0.01
tracks/0/type = "bezier"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:position:y")
tracks/0/path = NodePath("Body:scale:y")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0, -0.01, -0.25, 0, 0.25, 0),
"points": PackedFloat32Array(1, -0.25, 0, 0.12, -0.00966179, 0.500747, -0.13, 0.00874269, 0.25, 0),
"times": PackedFloat32Array(0, 0.2)
}
tracks/1/type = "bezier"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("MeshInstance3D:mesh:size:y")
tracks/1/path = NodePath("Body:position:y")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(0.02, -0.25, 0, 0.25, 0, 0.01, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0, 0.2)
}
tracks/2/type = "bezier"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("MeshInstance3D:position:y")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0, 0.005, -0.25, 0, 0.25, 0),
"points": PackedFloat32Array(0.0101447, -0.25, 0, 0.12, 0.000134136, 0.0051993, -0.12, 0.000145131, 0.25, 0),
"times": PackedFloat32Array(0, 0.2)
}
@ -79,26 +68,46 @@ _data = {
"down": SubResource("Animation_iu2ed")
}
[node name="Button" type="StaticBody3D" groups=["ui_focus"]]
[sub_resource type="BoxShape3D" id="BoxShape3D_bqjii"]
size = Vector3(0.0501598, 0.0195937, 0.0501598)
[node name="Button" type="Node3D" groups=["ui_focus"]]
script = ExtResource("1_74x7g")
label = "Example Text"
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_jwpm5")
[node name="Body" type="StaticBody3D" parent="." groups=["ui_focus_skip"]]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.01, 0)
collision_layer = 2
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Body"]
transform = Transform3D(0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 0, -0.005, 0)
mesh = ExtResource("2_cve3l")
skeleton = NodePath("../..")
surface_material_override/0 = SubResource("StandardMaterial3D_8s8ln")
[node name="CollisionShape3D" type="CollisionShape3D" parent="Body"]
shape = SubResource("ConvexPolygonShape3D_o4j7g")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_sbgno")
}
[node name="Label" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0.011, 0)
[node name="Label" type="Label3D" parent="Body"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0.005, 0)
pixel_size = 0.001
text = "Example Text"
font_size = 10
outline_size = 0
autowrap_mode = 3
width = 50.0
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_sbgno")
}
[node name="FingerArea" type="Area3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0101447, 0)
collision_layer = 4
collision_mask = 0
monitoring = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="FingerArea"]
shape = SubResource("BoxShape3D_bqjii")

View File

@ -68,6 +68,10 @@ func _process(_delta):
if get_tree().debug_collisions_hint && OS.get_name() != "Android":
_draw_debug_text_gaps()
func _on_press_down(event):
var pos_x = label.to_local(event.ray.get_collision_point()).x
text_handler.update_caret_position(pos_x)
func _on_press_move(event):
var ray_pos = event.ray.global_position
var ray_dir = -event.ray.global_transform.basis.z
@ -86,10 +90,7 @@ func _on_press_move(event):
caret.position.x = text_handler.get_caret_position()
label.text = text_handler.get_display_text()
func _on_focus_in(event):
var pos_x = label.to_local(event.ray.get_collision_point()).x
text_handler.update_caret_position(pos_x)
func _on_focus_in(_event):
caret.position.x = text_handler.get_caret_position()
label.text = text_handler.get_display_text()
caret.show()
@ -114,6 +115,7 @@ func update_caret_position(event):
func _on_focus_out(_event):
print("focus out")
animation.stop()
caret.hide()

View File

@ -53,6 +53,8 @@ _data = {
}
[node name="Input" type="StaticBody3D" groups=["ui_focus"]]
collision_layer = 2
collision_mask = 0
script = ExtResource("1_uml3t")
width = 0.2
text = "Example"

View File

@ -1,4 +1,4 @@
extends Object
extends RefCounted
var label: Label3D

View File

@ -8,6 +8,7 @@
script = ExtResource("1_rbo86")
[node name="Button" parent="." instance=ExtResource("2_go2es")]
focusable = true
[node name="Clickable" type="Node" parent="."]
script = ExtResource("3_6wicx")

View File

@ -1,7 +1,6 @@
extends Node3D
const Device = preload("./device/device.tscn")
const Entity = preload("./entity/entity.tscn")
const ButtonScene = preload("res://content/ui/components/button/button.tscn")
const EntityCreator = preload("./entity_creator.gd")
@onready var devices_node: GridContainer3D = $Devices
@ -101,33 +100,33 @@ func render_devices():
for device in page_devices:
var info = device.values()[0]
var device_instance = Device.instantiate()
device_instance.id = device.keys()[0]
device_instance.get_node("Clickable").on_click.connect(func(_event):
_on_device_click(device_instance.id)
var button_instance = ButtonScene.instantiate()
button_instance.label = info["name"]
button_instance.on_button_down.connect(func():
_on_device_click(device.keys()[0])
)
devices_node.add_child(device_instance)
device_instance.set_device_name.call_deferred(info["name"])
devices_node.add_child(button_instance)
devices_node._update_container()
func render_entities():
var entities = get_page()
var back_button = Entity.instantiate()
back_button.get_node("Clickable").on_click.connect(func(_event):
var back_button = ButtonScene.instantiate()
back_button.label = "arrow_back"
back_button.icon = true
back_button.on_button_down.connect(func():
_on_entity_click("#back")
)
devices_node.add_child(back_button)
back_button.set_entity_name("#back")
for entity in entities:
var entity_instance = Entity.instantiate()
entity_instance.get_node("Clickable").on_click.connect(func(_event):
var button_instance = ButtonScene.instantiate()
button_instance.label = entity
button_instance.on_button_down.connect(func():
_on_entity_click(entity)
)
devices_node.add_child(entity_instance)
entity_instance.set_entity_name(entity)
devices_node.add_child(button_instance)
devices_node._update_container()

View File

@ -1,9 +1,8 @@
[gd_scene load_steps=5 format=3 uid="uid://crrb0l3ekuotj"]
[gd_scene load_steps=4 format=3 uid="uid://crrb0l3ekuotj"]
[ext_resource type="Script" path="res://content/ui/menu/edit/edit_menu.gd" id="1_34cbn"]
[ext_resource type="Script" path="res://content/ui/menu/grid.gd" id="3_0xvyw"]
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="4_tvimg"]
[ext_resource type="Script" path="res://content/functions/clickable.gd" id="6_pf8jy"]
[node name="EditMenu" type="Node3D"]
script = ExtResource("1_34cbn")
@ -26,16 +25,12 @@ outline_size = 0
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
label = "navigate_next"
icon = true
[node name="Clickable" type="Node" parent="Buttons/NextPageButton"]
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
label = "navigate_before"
icon = true
[node name="Clickable" type="Node" parent="Buttons/PreviousPageButton"]
script = ExtResource("6_pf8jy")

View File

@ -1,4 +1,4 @@
extends Object
extends RefCounted
const Switch = preload("res://content/entities/switch/switch.tscn")
const Light = preload("res://content/entities/light/light.tscn")

View File

@ -1,5 +1,7 @@
extends Node3D
const Proxy = preload("res://lib/utils/proxy.gd")
@onready var _controller := XRHelpers.get_xr_controller(self)
@onready var nav_view = $AnimationContainer/Navigation/View
@ -34,10 +36,25 @@ func _ready():
show_menu = !show_menu
)
select_menu(nav_edit)
var nav_buttons = [
nav_view,
nav_edit,
nav_room,
nav_automate,
nav_settings
]
func _on_click(event):
select_menu(event.target)
for nav_button in nav_buttons:
var getter = func():
return nav_button == selected_nav
var setter = func(value):
if value:
select_menu(nav_button)
nav_button.external_value = Proxy.new(getter, setter)
select_menu(nav_edit)
func select_menu(nav):
if _is_valid_nav(nav) == false || selected_nav == nav:
@ -46,13 +63,15 @@ func select_menu(nav):
for child in content.get_children():
content.remove_child(child)
if selected_nav != null:
selected_nav.active = false
var old_nav = selected_nav
selected_nav = nav
if old_nav != null:
old_nav.update_animation()
if selected_nav != null:
selected_nav.active = true
selected_nav.update_animation()
var menu = _nav_to_menu(selected_nav)
if menu != null:
content.add_child(menu)

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=12 format=3 uid="uid://c3kdssrmv84kv"]
[gd_scene load_steps=13 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"]
@ -13,6 +13,9 @@
material = SubResource("StandardMaterial3D_ti5t2")
size = Vector3(0.3, 0.01, 0.3)
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_mgnm0"]
points = PackedVector3Array(-0.15, -0.005, -0.15, -0.15, 0.005, -0.15, 0.15, -0.005, -0.15, -0.15, -0.005, 0.15, -0.15, 0.005, 0.15, 0.15, 0.005, -0.15, 0.15, -0.005, 0.15, 0.15, 0.005, 0.15)
[sub_resource type="Animation" id="Animation_61md4"]
length = 0.001
tracks/0/type = "bezier"
@ -153,13 +156,17 @@ _data = {
[node name="Menu" type="Node3D"]
script = ExtResource("1_ng4u3")
[node name="AnimationContainer" type="Node3D" parent="."]
[node name="AnimationContainer" type="StaticBody3D" parent="."]
[node name="Background" type="MeshInstance3D" parent="AnimationContainer"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.21, 0, 0.15)
mesh = SubResource("BoxMesh_08du6")
skeleton = NodePath("../..")
[node name="CollisionShape3D" type="CollisionShape3D" parent="AnimationContainer"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.21, 0, 0.15)
shape = SubResource("ConvexPolygonShape3D_mgnm0")
[node name="Navigation" type="Node3D" parent="AnimationContainer"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.06, 0, 0)
@ -168,35 +175,30 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.03)
label = "visibility"
icon = true
toggleable = true
external_state = true
[node name="Edit" parent="AnimationContainer/Navigation" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.09)
label = "widgets"
icon = true
toggleable = true
external_state = true
[node name="Room" parent="AnimationContainer/Navigation" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.15)
label = "view_in_ar"
icon = true
toggleable = true
external_state = true
[node name="Automate" parent="AnimationContainer/Navigation" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.21)
label = "schema"
icon = true
toggleable = true
external_state = true
[node name="Settings" parent="AnimationContainer/Navigation" instance=ExtResource("5_w4i01")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.03, 0, 0.27)
label = "settings"
icon = true
toggleable = true
external_state = true
[node name="Content" type="Node3D" parent="AnimationContainer"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.06, 0, 0)

View File

@ -27,10 +27,17 @@ func _ready():
add_corner(event.ray.get_collision_point())
)
toggle_edit_button.get_node("Clickable").on_press_up.connect(func(event):
edit_enabled = event.target.active
toggle_edit_button.on_button_down.connect(func():
edit_enabled = true
wall_corners.visible = true
wall_edges.visible = true
wall_mesh.visible = false
)
toggle_edit_button.on_button_up.connect(func():
edit_enabled = false
if edit_enabled == false:
wall_corners.visible = false
wall_edges.visible = false
wall_mesh.mesh = generate_mesh()
@ -45,14 +52,13 @@ func _ready():
for collision in collisions:
var static_body = StaticBody3D.new()
static_body.set_collision_layer_value(4, true)
static_body.set_collision_layer_value(5, true)
static_body.collision_mask = 0
static_body.add_child(collision)
wall_collisions.add_child(static_body)
wall_mesh.visible = true
else:
wall_corners.visible = true
wall_edges.visible = true
wall_mesh.visible = false
)
func generate_mesh():

View File

@ -18,6 +18,8 @@ script = ExtResource("1_ch4jb")
[node name="TeleportRoot" type="Node3D" parent="."]
[node name="Ground" type="StaticBody3D" parent="TeleportRoot"]
collision_layer = 24
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="TeleportRoot/Ground"]
shape = SubResource("WorldBoundaryShape3D_08sv0")

View File

@ -9,6 +9,8 @@ bounce = 0.7
radius = 0.08
[node name="Ball" type="RigidBody3D"]
collision_layer = 8
collision_mask = 24
physics_material_override = SubResource("PhysicsMaterial_f6jtg")
angular_damp = 4.0

View File

@ -36,7 +36,7 @@ outline_size = 0
autowrap_mode = 3
[node name="Room" type="Label3D" parent="Content"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, -0.06)
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 9.31323e-10, -0.049608)
pixel_size = 0.001
modulate = Color(0, 0, 0, 1)
text = "This work is based on \"Living Room\" (https://sketchfab.com/3d-models/living-room-2978ca6c93fb4f5c83e346d5ecdef0b0) by Chin.Seng.Choy (https://sketchfab.com/Chin.Seng.Choy) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)"

View File

@ -3,7 +3,7 @@ extends Node3D
const ball_scene = preload("./ball.tscn")
const credits_scene = preload("./credits.tscn")
@onready var clickable = $Content/Button/Clickable
@onready var ball_button = $Content/Button
@onready var connection_status = $Content/ConnectionStatus
@onready var input_url = $Content/InputURL
@ -15,10 +15,12 @@ const credits_scene = preload("./credits.tscn")
func _ready():
background.visible = false
clickable.on_click.connect(func(event):
ball_button.on_button_down.connect(func():
var ball = ball_scene.instantiate()
ball.transform = event.controller.transform
ball.linear_velocity = -event.controller.transform.basis.z * 5 + Vector3(0, 5, 0)
var controller = XRHelpers.get_right_controller(self)
ball.transform = controller.transform
ball.linear_velocity = -controller.transform.basis.z * 5 + Vector3(0, 5, 0)
get_tree().root.add_child(ball)
)

View File

@ -43,9 +43,9 @@ launcher_icons/adaptive_foreground_432x432=""
launcher_icons/adaptive_background_432x432=""
graphics/opengl_debug=false
xr_features/xr_mode=1
xr_features/hand_tracking=0
xr_features/hand_tracking=1
xr_features/hand_tracking_frequency=1
xr_features/passthrough=1
xr_features/passthrough=2
screen/immersive_mode=true
screen/support_small=true
screen/support_normal=true

View File

@ -43,9 +43,9 @@ launcher_icons/adaptive_foreground_432x432=""
launcher_icons/adaptive_background_432x432=""
graphics/opengl_debug=false
xr_features/xr_mode=1
xr_features/hand_tracking=0
xr_features/hand_tracking=1
xr_features/hand_tracking_frequency=1
xr_features/passthrough=1
xr_features/passthrough=2
screen/immersive_mode=true
screen/support_small=true
screen/support_normal=true

View File

@ -1,6 +1,5 @@
extends Event
class_name EventFocus
var ray: RayCast3D
var target: Node
var previous_target: Node

View File

@ -0,0 +1,7 @@
extends EventBubble
class_name EventPointer
const Initiator = preload("res://lib/utils/pointer/initiator.gd")
var initiator: Initiator
var ray: RayCast3D

View File

@ -1,6 +0,0 @@
extends EventBubble
class_name EventRay
var controller: XRController3D
var is_right_controller: bool
var ray: RayCast3D

12
lib/events/event_touch.gd Normal file
View File

@ -0,0 +1,12 @@
extends EventBubble
class_name EventTouch
const Finger = preload("res://lib/utils/touch/finger.gd")
var fingers: Array[Finger] = []
func has_finger(finger: Finger.Type):
for f in fingers:
if f.type == finger:
return true
return false

View File

@ -4,15 +4,15 @@ const FN_PREFIX = "_on_"
const SIGNAL_PREFIX = "on_"
# Interaction Events
signal on_click(event: EventRay)
signal on_press_down(event: EventRay)
signal on_press_move(event: EventRay)
signal on_press_up(event: EventRay)
signal on_grab_down(event: EventRay)
signal on_grab_move(event: EventRay)
signal on_grab_up(event: EventRay)
signal on_ray_enter(event: EventRay)
signal on_ray_leave(event: EventRay)
signal on_click(event: EventPointer)
signal on_press_down(event: EventPointer)
signal on_press_move(event: EventPointer)
signal on_press_up(event: EventPointer)
signal on_grab_down(event: EventPointer)
signal on_grab_move(event: EventPointer)
signal on_grab_up(event: EventPointer)
signal on_ray_enter(event: EventPointer)
signal on_ray_leave(event: EventPointer)
signal on_key_down(event: EventKey)
signal on_key_up(event: EventKey)
@ -20,43 +20,53 @@ signal on_key_up(event: EventKey)
signal on_focus_in(event: EventFocus)
signal on_focus_out(event: EventFocus)
signal on_touch_enter(event: EventTouch)
signal on_touch_move(event: EventTouch)
signal on_touch_leave(event: EventTouch)
var _active_node: Node = null
func emit(type: String, event: Event):
if event is EventBubble:
_bubble_call(type, event.target, event)
if type == "press_down":
_handle_focus(event)
else:
_root_call(type, event)
func is_focused(node: Node):
return _active_node == node
func _handle_focus(event: EventRay):
if event.target != null && event.target.is_in_group("ui_focus_skip"):
return
func _handle_focus(target: Variant, event: EventBubble):
print("focus ", target, " ", target.get_groups(), " ", event)
if target != null:
if target.is_in_group("ui_focus_skip"):
return false
if target.is_in_group("ui_focus_stop"):
return true
var event_focus = EventFocus.new()
event_focus.previous_target = _active_node
event_focus.target = event.target
event_focus.ray = event.ray
event_focus.target = target
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:
if target == null || target.is_in_group("ui_focus") == false:
_active_node = null
return
return false
_active_node = event.target
_active_node = target
print("focus", _active_node )
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):
return true
func _bubble_call(type: String, target: Variant, event: EventBubble, focused = false):
if target == null:
return false
@ -70,6 +80,9 @@ func _bubble_call(type: String, target: Variant, event: EventBubble):
if event.bubbling == false:
return false
if (type == "press_down" || type == "touch_enter") && focused == false:
focused = _handle_focus(target, event)
for child in target.get_children():
if child is Function && child.has_method(FN_PREFIX + type):
child.call(FN_PREFIX + type, event)
@ -77,7 +90,7 @@ func _bubble_call(type: String, target: Variant, event: EventBubble):
var parent = target.get_parent()
if parent != null && parent is Node:
_bubble_call(type, parent, event)
_bubble_call(type, parent, event, focused)
else:
# in case the top has been reached
_root_call(type, event)

View File

@ -0,0 +1,22 @@
extends RefCounted
enum Type {
CONTROLLER_LEFT,
CONTROLLER_RIGHT,
HAND_LEFT,
HAND_RIGHT,
}
enum EventType {
GRIP,
TRIGGER,
}
signal on_press(type: EventType)
signal on_release(type: EventType)
var node: Node3D
var type: Type
func is_right() -> bool:
return type == Type.CONTROLLER_RIGHT || type == Type.HAND_RIGHT

View File

@ -0,0 +1,98 @@
extends Node
const Initiator = preload("./initiator.gd")
var initiator: Initiator
var ray: RayCast3D
var timespan_click = 400.0
var last_collided: Object = null
var is_pressed := false
var is_grabbed := false
var time_pressed := 0.0
var moved := false
var click_point := Vector3.ZERO
func _init(initiator: Initiator, ray: RayCast3D):
self.initiator = initiator
self.ray = ray
func _ready():
initiator.on_press.connect(_on_pressed)
initiator.on_release.connect(_on_released)
func _physics_process(_delta):
_handle_enter_leave()
_handle_move()
func _handle_move():
var time_passed = Time.get_ticks_msec() - time_pressed
if time_passed <= timespan_click || (is_pressed == false && is_grabbed == false):
return
moved = true
# reset if last_collided gets deleted
if is_instance_valid(last_collided) == false:
last_collided = null
return
if is_pressed:
_emit_event("press_move", last_collided )
if is_grabbed:
_emit_event("grab_move", last_collided )
func _handle_enter_leave():
var collider = ray.get_collider()
if collider == last_collided || is_grabbed || is_pressed:
return
_emit_event("ray_enter", collider )
_emit_event("ray_leave", last_collided )
last_collided = collider
func _on_pressed(type: Initiator.EventType):
var collider = ray.get_collider()
if collider == null:
return
match type:
Initiator.EventType.TRIGGER:
is_pressed = true
time_pressed = Time.get_ticks_msec()
click_point = ray.get_collision_point()
_emit_event("press_down", collider )
Initiator.EventType.GRIP:
is_grabbed = true
click_point = ray.get_collision_point()
_emit_event("grab_down", collider )
func _on_released(type: Initiator.EventType):
match type:
Initiator.EventType.TRIGGER:
if is_pressed:
if moved == false:
_emit_event("click", last_collided )
_emit_event("press_up", last_collided )
is_pressed = false
last_collided = null
moved = false
Initiator.EventType.GRIP:
if is_grabbed:
_emit_event("grab_up", last_collided )
is_grabbed = false
last_collided = null
moved = false
func _emit_event(type: String, target):
var event = EventPointer.new()
event.initiator = initiator
event.target = target
event.ray = ray
EventSystem.emit(type, event)

14
lib/utils/proxy.gd Normal file
View File

@ -0,0 +1,14 @@
extends RefCounted
var gettable: Callable
var settable: Callable
func _init(gettable: Callable, settable: Callable):
self.gettable = gettable
self.settable = settable
var value: Variant:
get:
return gettable.call()
set(new_value):
settable.call(new_value)

17
lib/utils/touch/finger.gd Normal file
View File

@ -0,0 +1,17 @@
extends RefCounted
enum Type {
THUMB_RIGHT,
INDEX_RIGHT,
MIDDLE_RIGHT,
RING_RIGHT,
LITTLE_RIGHT,
THUMB_LEFT,
INDEX_LEFT,
MIDDLE_LEFT,
RING_LEFT,
LITTLE_LEFT,
}
var type: Type
var area: Area3D

57
lib/utils/touch/touch.gd Normal file
View File

@ -0,0 +1,57 @@
extends Node
const Finger = preload("res://lib/utils/touch/finger.gd")
## Record<Finger.Type, Area3D>
var finger_areas: Dictionary
var areas_entered = {}
func _init(finger_areas: Dictionary):
self.finger_areas = finger_areas
func _ready():
for finger_type in finger_areas.keys():
finger_areas[finger_type].area_entered.connect(func(area):
_on_area_entered(finger_type, area)
)
finger_areas[finger_type].area_exited.connect(func(area):
_on_area_exited(finger_type, area)
)
func _physics_process(_delta):
for area in areas_entered.keys():
_emit_event("touch_move", area)
func _on_area_entered(finger_type, area):
if areas_entered.has(area):
if !areas_entered[area].has(finger_type):
areas_entered[area].append(finger_type)
_emit_event("touch_enter", area)
else:
areas_entered[area] = [finger_type]
_emit_event("touch_enter", area)
func _on_area_exited(finger_type, area):
if areas_entered.has(area):
if areas_entered[area].has(finger_type):
areas_entered[area].erase(finger_type)
if areas_entered[area].size() == 0:
_emit_event("touch_leave", area)
areas_entered.erase(area)
func _emit_event(type: String, target):
var event = EventTouch.new()
event.target = target
var fingers: Array[Finger] = []
for finger_type in areas_entered[target]:
var finger = Finger.new()
finger.type = finger_type
finger.area = finger_areas[finger_type]
fingers.append(finger)
event.fingers = fingers
EventSystem.emit(type, event)

View File

@ -28,10 +28,22 @@ EventSystem="*res://lib/globals/event_system.gd"
enabled=PackedStringArray("res://addons/godot-xr-tools/plugin.cfg")
[filesystem]
import/fbx/enabled=false
[gui]
theme/custom_font="res://assets/fonts/ui_font_500.tres"
[layer_names]
3d_physics/layer_1="entities"
3d_physics/layer_2="interface"
3d_physics/layer_3="touch"
3d_physics/layer_4="physics"
3d_physics/layer_5="room"
[rendering]
renderer/rendering_method="mobile"