Merge pull request #53 from Nitwel/testing
Implement experimental handtracking
This commit is contained in:
commit
0c5cfba55f
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -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
|
||||
|
|
23
README.md
23
README.md
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
3
assets/immersive_home/button.mtl
Normal file
3
assets/immersive_home/button.mtl
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:86eced068bcbed2d727b107358398aff996d92dddedaeff7277430262507bcb1
|
||||
size 233
|
3
assets/immersive_home/button.obj
Normal file
3
assets/immersive_home/button.obj
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:26fbc4673b78bf69b4955cd131e2484f705d833528cb3040223434c8bec9fe18
|
||||
size 92814
|
21
assets/immersive_home/button.obj.import
Normal file
21
assets/immersive_home/button.obj.import
Normal 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
|
3
assets/models/hands_steam/left_hand.glb
Normal file
3
assets/models/hands_steam/left_hand.glb
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:135189e6a2caab7d5fa0182feda4c2c7b1a9485bc5a7b27b0fe7b5b5ed7e33eb
|
||||
size 40061376
|
32
assets/models/hands_steam/left_hand.glb.import
Normal file
32
assets/models/hands_steam/left_hand.glb.import
Normal 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
|
3
assets/models/hands_steam/left_hand_file2.png
Normal file
3
assets/models/hands_steam/left_hand_file2.png
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:285a2e53aa6d3054749ffcd965a193cb1ddfeedd0bde1f33c8e339eb3d6e077e
|
||||
size 30680477
|
37
assets/models/hands_steam/left_hand_file2.png.import
Normal file
37
assets/models/hands_steam/left_hand_file2.png.import
Normal 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
|
3
assets/models/hands_steam/left_hand_file3.png
Normal file
3
assets/models/hands_steam/left_hand_file3.png
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d7877cf67239ad881c8c4fa5773b9f09d7f35ca763345163800d18e25a52253c
|
||||
size 18391772
|
37
assets/models/hands_steam/left_hand_file3.png.import
Normal file
37
assets/models/hands_steam/left_hand_file3.png.import
Normal 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
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:135189e6a2caab7d5fa0182feda4c2c7b1a9485bc5a7b27b0fe7b5b5ed7e33eb
|
||||
size 40061376
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:285a2e53aa6d3054749ffcd965a193cb1ddfeedd0bde1f33c8e339eb3d6e077e
|
||||
size 30680477
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d7877cf67239ad881c8c4fa5773b9f09d7f35ca763345163800d18e25a52253c
|
||||
size 18391772
|
|
@ -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
|
3
assets/models/hands_steam/right_hand.glb
Normal file
3
assets/models/hands_steam/right_hand.glb
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d7d207229f1878c83742db31a111de44f7cf3136d03a3e7bf1f9c786bc30d550
|
||||
size 40061252
|
32
assets/models/hands_steam/right_hand.glb.import
Normal file
32
assets/models/hands_steam/right_hand.glb.import
Normal 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
|
3
assets/models/hands_steam/right_hand_file2.png
Normal file
3
assets/models/hands_steam/right_hand_file2.png
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:285a2e53aa6d3054749ffcd965a193cb1ddfeedd0bde1f33c8e339eb3d6e077e
|
||||
size 30680477
|
37
assets/models/hands_steam/right_hand_file2.png.import
Normal file
37
assets/models/hands_steam/right_hand_file2.png.import
Normal 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
|
3
assets/models/hands_steam/right_hand_file3.png
Normal file
3
assets/models/hands_steam/right_hand_file3.png
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d7877cf67239ad881c8c4fa5773b9f09d7f35ca763345163800d18e25a52253c
|
||||
size 18391772
|
37
assets/models/hands_steam/right_hand_file3.png.import
Normal file
37
assets/models/hands_steam/right_hand_file3.png.import
Normal 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
|
|
@ -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")
|
||||
|
|
|
@ -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="."]
|
||||
|
|
|
@ -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="."]
|
||||
|
|
|
@ -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="."]
|
||||
|
|
|
@ -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)
|
|
@ -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()
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
106
content/system/hands/hands.gd
Normal file
106
content/system/hands/hands.gd
Normal 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
|
160
content/system/hands/hands.tscn
Normal file
160
content/system/hands/hands.tscn
Normal 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"]
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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 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
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
extends Object
|
||||
extends RefCounted
|
||||
|
||||
var label: Label3D
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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/)"
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
extends Event
|
||||
class_name EventFocus
|
||||
|
||||
var ray: RayCast3D
|
||||
var target: Node
|
||||
var previous_target: Node
|
7
lib/events/event_pointer.gd
Normal file
7
lib/events/event_pointer.gd
Normal 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
|
|
@ -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
12
lib/events/event_touch.gd
Normal 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
|
|
@ -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)
|
||||
|
|
22
lib/utils/pointer/initiator.gd
Normal file
22
lib/utils/pointer/initiator.gd
Normal 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
|
98
lib/utils/pointer/pointer.gd
Normal file
98
lib/utils/pointer/pointer.gd
Normal 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
14
lib/utils/proxy.gd
Normal 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
17
lib/utils/touch/finger.gd
Normal 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
57
lib/utils/touch/touch.gd
Normal 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)
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue
Block a user