add hand tracking

This commit is contained in:
Nitwel 2023-11-27 00:23:19 +01:00
parent dd3dd623ca
commit fdbd3f9d96
39 changed files with 727 additions and 158 deletions

View File

@ -117,15 +117,15 @@ It is also possible to bubble up information by returning a dictionary from a fu
| Function called | Args | Description |
| -- | -- | -- |
| `_on_click` | `[event: EventRay]` | The back trigger button has been pressed and released |
| `_on_press_down` | `[event: EventRay]` | The back trigger button has been pressed down |
| `_on_press_move` | `[event: EventRay]` | The back trigger button has been moved while pressed down |
| `_on_press_up` | `[event: EventRay]` | The back trigger button has been released |
| `_on_grab_down` | `[event: EventRay]` | The side grab button been pressed down |
| `_on_grab_move` | `[event: EventRay]` | The side grab button been pressed down |
| `_on_grab_up` | `[event: EventRay]` | The side grab button been released |
| `_on_ray_enter` | `[event: EventRay]` | The ray-cast enters the the collision body |
| `_on_ray_leave` | `[event: EventRay]` | The ray-cast leaves the the collision body |
| `_on_click` | `[event: EventPointer]` | The back trigger button has been pressed and released |
| `_on_press_down` | `[event: EventPointer]` | The back trigger button has been pressed down |
| `_on_press_move` | `[event: EventPointer]` | The back trigger button has been moved while pressed down |
| `_on_press_up` | `[event: EventPointer]` | The back trigger button has been released |
| `_on_grab_down` | `[event: EventPointer]` | The side grab button been pressed down |
| `_on_grab_move` | `[event: EventPointer]` | The side grab button been pressed down |
| `_on_grab_up` | `[event: EventPointer]` | The side grab button been released |
| `_on_ray_enter` | `[event: EventPointer]` | The ray-cast enters the the collision body |
| `_on_ray_leave` | `[event: EventPointer]` | The ray-cast leaves the the collision body |
| `_on_key_down` | `[event: EventKey]` | The ray-cast leaves the the collision body |
| `_on_key_up` | `[event: EventKey]` | The ray-cast leaves the the collision body |
| `_on_focus_in` | `[event: EventFocus]` | The node is got focused |

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
[ext_resource type="Script" path="res://content/system/controller_left/controller_left.gd" id="1_2j3qs"]
[ext_resource type="PackedScene" uid="uid://c3kdssrmv84kv" path="res://content/ui/menu/menu.tscn" id="1_ccbr3"]
[ext_resource type="PackedScene" uid="uid://cj42our8uhfq6" path="res://assets/models/trash_bin/trash_bin.gltf" id="3_m33ce"]
[ext_resource type="PackedScene" uid="uid://dqjcqdhe3rbtn" path="res://assets/models/trash_bin/trash_bin.gltf" id="3_m33ce"]
[ext_resource type="PackedScene" uid="uid://d3f8glx1xgm5w" path="res://content/system/raycast/raycast.tscn" id="4_n7lao"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"]

View File

@ -0,0 +1,70 @@
extends Node3D
const Pointer = preload("res://lib/utils/pointer/pointer.gd")
const Initiator = preload("res://lib/utils/pointer/initiator.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 pointer: Pointer
var press_distance = 0.03
var grip_distance = 0.05
var pressed_left = false
var pressed_right = false
var grabbed_left = false
var grabbed_right = false
func _ready():
_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)
if hand == hand_left:
if distance_trigger <= press_distance && !pressed_left:
initiator.on_press.emit(Initiator.EventType.TRIGGER)
pressed_left = true
elif distance_trigger > press_distance && pressed_left:
initiator.on_release.emit(Initiator.EventType.TRIGGER)
pressed_left = false
if distance_grab <= grip_distance && !grabbed_left:
initiator.on_press.emit(Initiator.EventType.GRIP)
grabbed_left = true
elif distance_grab > grip_distance && grabbed_left:
initiator.on_release.emit(Initiator.EventType.GRIP)
grabbed_left = false
else:
if distance_trigger <= press_distance && !pressed_right:
initiator.on_press.emit(Initiator.EventType.TRIGGER)
pressed_right = true
elif distance_trigger > press_distance && pressed_right:
initiator.on_release.emit(Initiator.EventType.TRIGGER)
pressed_right = false
if distance_grab <= grip_distance && !grabbed_right:
initiator.on_press.emit(Initiator.EventType.GRIP)
grabbed_right = true
elif distance_grab > grip_distance && grabbed_right:
initiator.on_release.emit(Initiator.EventType.GRIP)
grabbed_right = false

View File

@ -0,0 +1,86 @@
[gd_scene load_steps=4 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"]
[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="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="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="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="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
[editable path="XRHandLeft/left_hand"]
[editable path="XRHandRight/right_hand"]

View File

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

View File

@ -18,6 +18,6 @@ lower_fade = 0.000919435
[node name="Cursor" type="Node3D" parent="."]
[node name="CursorSprite" type="Sprite3D" parent="Cursor"]
transform = Transform3D(0.03, 3.25261e-20, -2.20405e-39, -3.25261e-20, 0.03, -2.03288e-21, 0, 2.03288e-21, 0.03, 0, 0, 0)
transform = Transform3D(0.03, 2.71051e-20, 0, -5.42101e-20, 0.03, -2.03288e-21, -2.46521e-33, 2.5411e-21, 0.03, 0, 0, 0)
pixel_size = 0.001
texture = ExtResource("1_2f2iv")

View File

@ -5,7 +5,6 @@
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_8s8ln"]
transparency = 1
cull_mode = 2
albedo_color = Color(0, 0.501961, 0.886275, 1)
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_o4j7g"]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,15 +4,15 @@ const FN_PREFIX = "_on_"
const SIGNAL_PREFIX = "on_"
# Interaction Events
signal on_click(event: EventRay)
signal on_press_down(event: EventRay)
signal on_press_move(event: EventRay)
signal on_press_up(event: EventRay)
signal on_grab_down(event: EventRay)
signal on_grab_move(event: EventRay)
signal on_grab_up(event: EventRay)
signal on_ray_enter(event: EventRay)
signal on_ray_leave(event: EventRay)
signal on_click(event: EventPointer)
signal on_press_down(event: EventPointer)
signal on_press_move(event: EventPointer)
signal on_press_up(event: EventPointer)
signal on_grab_down(event: EventPointer)
signal on_grab_move(event: EventPointer)
signal on_grab_up(event: EventPointer)
signal on_ray_enter(event: EventPointer)
signal on_ray_leave(event: EventPointer)
signal on_key_down(event: EventKey)
signal on_key_up(event: EventKey)
@ -33,7 +33,7 @@ func emit(type: String, event: Event):
func is_focused(node: Node):
return _active_node == node
func _handle_focus(event: EventRay):
func _handle_focus(event: EventPointer):
if event.target != null && event.target.is_in_group("ui_focus_skip"):
return

View File

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

View File

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

View File

@ -28,6 +28,10 @@ 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"