update to latest xr tools
This commit is contained in:
parent
a0433a5659
commit
2326534296
|
@ -1,3 +1,17 @@
|
|||
# 4.3.0
|
||||
- Upgraded project to Godot 4.1 as the new minimum version.
|
||||
- Added reporting of stage load errors.
|
||||
- Blend player height changes and prevent the player from standing up under a low ceiling.
|
||||
- **minor-breakage** Added support for swapping held items between hands.
|
||||
- Added jog-in-place movement provider.
|
||||
- Added support for grappling on GridMap instances
|
||||
- **breakage** Added support for two-handed grabbing.
|
||||
- Added support for snapping hands to grab-points.
|
||||
- Added support for world-grab movement.
|
||||
- Fixed editor errors when using hand physics bones.
|
||||
- Added support for climbable grab-points.
|
||||
- Added control of keyboard or gamepad inputs to Viewport2Din3D instances.
|
||||
|
||||
# 4.2.1
|
||||
- Fixed snap-zones showing highlight when disabled.
|
||||
- Fixed pickup leaving target highlighted after picking up.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dbbxlk5acoxfg"
|
||||
uid="uid://ocyj01x5mtt7"
|
||||
path.s3tc="res://.godot/imported/Hold trigger to continue.png-ce0a3a4de13c262f7015326bad2cb09d.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/Hold trigger to continue.png-ce0a3a4de13c262f7015326bad2cb09d.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b77u06jwo4l5y"
|
||||
uid="uid://clbtsf0ahb3fm"
|
||||
path.s3tc="res://.godot/imported/progress_bar.png-2ef3cbffca173889900be004fdeb1700.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/progress_bar.png-2ef3cbffca173889900be004fdeb1700.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://cggrrnkgc7ufo"]
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/audio/surface_audio.gd" id="1"]
|
||||
[ext_resource path="res://addons/godot-xr-tools/audio/surface_audio.gd" type="Script" id=1]
|
||||
|
||||
[node name="SurfaceAudio" type="Node"]
|
||||
script = ExtResource("1")
|
||||
script = ExtResource( 1 )
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dd81tkixfsdrw"
|
||||
uid="uid://dhnfbf4p0s74"
|
||||
path="res://.godot/imported/audio.svg-20d7f0b624a1b2ef54f1b4d12970c8d0.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://8krthn43snhi"
|
||||
uid="uid://cyg33jxco0rh6"
|
||||
path="res://.godot/imported/body.svg-324e141d452c32f3136ca97c338025b4.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cqjrs44rcon7m"
|
||||
uid="uid://bfkcd3fkyahqu"
|
||||
path="res://.godot/imported/foot.svg-9e361563e010aa07be49bfb25fdb6639.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b3tktceuqduij"
|
||||
uid="uid://b5vxil50s0ofi"
|
||||
path="res://.godot/imported/function.svg-52c5f936037e0f38a4da2b1e16ae67fe.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://duxf7oimwxodc"
|
||||
uid="uid://beko1qhyybx7e"
|
||||
path="res://.godot/imported/hand.svg-a05486d804ef16320d6cf54e06292b8f.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bj0d07w1a7blg"
|
||||
uid="uid://04fn15h4x333"
|
||||
path="res://.godot/imported/movement_provider.svg-3c994cf0a3775c20f333be563d69fbf8.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://xtrkapd7af3l"
|
||||
uid="uid://b6gwa6o27pbry"
|
||||
path="res://.godot/imported/node.svg-37d53571b4a4459efefcc791c5402b4f.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -6,11 +6,10 @@
|
|||
[sub_resource type="ArrayMesh" id="ArrayMesh_yyajy"]
|
||||
_surfaces = [{
|
||||
"aabb": AABB(-2, -2, 0, 4, 4, 1e-05),
|
||||
"format": 34359742465,
|
||||
"format": 4097,
|
||||
"index_count": 192,
|
||||
"index_data": PackedByteArray(32, 0, 33, 0, 1, 0, 32, 0, 1, 0, 0, 0, 33, 0, 34, 0, 2, 0, 33, 0, 2, 0, 1, 0, 34, 0, 35, 0, 3, 0, 34, 0, 3, 0, 2, 0, 35, 0, 36, 0, 4, 0, 35, 0, 4, 0, 3, 0, 36, 0, 37, 0, 5, 0, 36, 0, 5, 0, 4, 0, 37, 0, 38, 0, 6, 0, 37, 0, 6, 0, 5, 0, 38, 0, 39, 0, 7, 0, 38, 0, 7, 0, 6, 0, 39, 0, 40, 0, 8, 0, 39, 0, 8, 0, 7, 0, 40, 0, 41, 0, 9, 0, 40, 0, 9, 0, 8, 0, 41, 0, 42, 0, 10, 0, 41, 0, 10, 0, 9, 0, 42, 0, 43, 0, 11, 0, 42, 0, 11, 0, 10, 0, 43, 0, 44, 0, 12, 0, 43, 0, 12, 0, 11, 0, 44, 0, 45, 0, 13, 0, 44, 0, 13, 0, 12, 0, 45, 0, 46, 0, 14, 0, 45, 0, 14, 0, 13, 0, 46, 0, 47, 0, 15, 0, 46, 0, 15, 0, 14, 0, 47, 0, 48, 0, 16, 0, 47, 0, 16, 0, 15, 0, 48, 0, 49, 0, 17, 0, 48, 0, 17, 0, 16, 0, 49, 0, 50, 0, 18, 0, 49, 0, 18, 0, 17, 0, 50, 0, 51, 0, 19, 0, 50, 0, 19, 0, 18, 0, 51, 0, 52, 0, 20, 0, 51, 0, 20, 0, 19, 0, 52, 0, 53, 0, 21, 0, 52, 0, 21, 0, 20, 0, 53, 0, 54, 0, 22, 0, 53, 0, 22, 0, 21, 0, 54, 0, 55, 0, 23, 0, 54, 0, 23, 0, 22, 0, 55, 0, 56, 0, 24, 0, 55, 0, 24, 0, 23, 0, 56, 0, 57, 0, 25, 0, 56, 0, 25, 0, 24, 0, 57, 0, 58, 0, 26, 0, 57, 0, 26, 0, 25, 0, 58, 0, 59, 0, 27, 0, 58, 0, 27, 0, 26, 0, 59, 0, 60, 0, 28, 0, 59, 0, 28, 0, 27, 0, 60, 0, 61, 0, 29, 0, 60, 0, 29, 0, 28, 0, 61, 0, 62, 0, 30, 0, 61, 0, 30, 0, 29, 0, 62, 0, 63, 0, 31, 0, 62, 0, 31, 0, 30, 0, 63, 0, 32, 0, 0, 0, 63, 0, 0, 0, 31, 0),
|
||||
"primitive": 3,
|
||||
"uv_scale": Vector4(0, 0, 0, 0),
|
||||
"vertex_count": 64,
|
||||
"vertex_data": PackedByteArray(0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 190, 20, 123, 63, 194, 197, 71, 190, 0, 0, 0, 0, 94, 131, 108, 63, 22, 239, 195, 190, 0, 0, 0, 0, 49, 219, 84, 63, 218, 57, 14, 191, 0, 0, 0, 0, 243, 4, 53, 63, 243, 4, 53, 191, 0, 0, 0, 0, 218, 57, 14, 63, 49, 219, 84, 191, 0, 0, 0, 0, 21, 239, 195, 62, 94, 131, 108, 191, 0, 0, 0, 0, 196, 197, 71, 62, 190, 20, 123, 191, 0, 0, 0, 0, 46, 189, 59, 179, 0, 0, 128, 191, 0, 0, 0, 0, 194, 197, 71, 190, 190, 20, 123, 191, 0, 0, 0, 0, 20, 239, 195, 190, 95, 131, 108, 191, 0, 0, 0, 0, 217, 57, 14, 191, 50, 219, 84, 191, 0, 0, 0, 0, 243, 4, 53, 191, 243, 4, 53, 191, 0, 0, 0, 0, 50, 219, 84, 191, 217, 57, 14, 191, 0, 0, 0, 0, 94, 131, 108, 191, 23, 239, 195, 190, 0, 0, 0, 0, 191, 20, 123, 191, 193, 197, 71, 190, 0, 0, 0, 0, 0, 0, 128, 191, 46, 189, 187, 51, 0, 0, 0, 0, 191, 20, 123, 191, 189, 197, 71, 62, 0, 0, 0, 0, 94, 131, 108, 191, 21, 239, 195, 62, 0, 0, 0, 0, 48, 219, 84, 191, 219, 57, 14, 63, 0, 0, 0, 0, 244, 4, 53, 191, 242, 4, 53, 63, 0, 0, 0, 0, 221, 57, 14, 191, 47, 219, 84, 63, 0, 0, 0, 0, 26, 239, 195, 190, 94, 131, 108, 63, 0, 0, 0, 0, 198, 197, 71, 190, 190, 20, 123, 63, 0, 0, 0, 0, 46, 222, 76, 50, 0, 0, 128, 63, 0, 0, 0, 0, 200, 197, 71, 62, 190, 20, 123, 63, 0, 0, 0, 0, 27, 239, 195, 62, 93, 131, 108, 63, 0, 0, 0, 0, 215, 57, 14, 63, 51, 219, 84, 63, 0, 0, 0, 0, 242, 4, 53, 63, 245, 4, 53, 63, 0, 0, 0, 0, 49, 219, 84, 63, 219, 57, 14, 63, 0, 0, 0, 0, 95, 131, 108, 63, 21, 239, 195, 62, 0, 0, 0, 0, 191, 20, 123, 63, 188, 197, 71, 62, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 190, 20, 251, 63, 194, 197, 199, 190, 0, 0, 0, 0, 94, 131, 236, 63, 22, 239, 67, 191, 0, 0, 0, 0, 49, 219, 212, 63, 218, 57, 142, 191, 0, 0, 0, 0, 243, 4, 181, 63, 243, 4, 181, 191, 0, 0, 0, 0, 218, 57, 142, 63, 49, 219, 212, 191, 0, 0, 0, 0, 21, 239, 67, 63, 94, 131, 236, 191, 0, 0, 0, 0, 196, 197, 199, 62, 190, 20, 251, 191, 0, 0, 0, 0, 46, 189, 187, 179, 0, 0, 0, 192, 0, 0, 0, 0, 194, 197, 199, 190, 190, 20, 251, 191, 0, 0, 0, 0, 20, 239, 67, 191, 95, 131, 236, 191, 0, 0, 0, 0, 217, 57, 142, 191, 50, 219, 212, 191, 0, 0, 0, 0, 243, 4, 181, 191, 243, 4, 181, 191, 0, 0, 0, 0, 50, 219, 212, 191, 217, 57, 142, 191, 0, 0, 0, 0, 94, 131, 236, 191, 23, 239, 67, 191, 0, 0, 0, 0, 191, 20, 251, 191, 193, 197, 199, 190, 0, 0, 0, 0, 0, 0, 0, 192, 46, 189, 59, 52, 0, 0, 0, 0, 191, 20, 251, 191, 189, 197, 199, 62, 0, 0, 0, 0, 94, 131, 236, 191, 21, 239, 67, 63, 0, 0, 0, 0, 48, 219, 212, 191, 219, 57, 142, 63, 0, 0, 0, 0, 244, 4, 181, 191, 242, 4, 181, 63, 0, 0, 0, 0, 221, 57, 142, 191, 47, 219, 212, 63, 0, 0, 0, 0, 26, 239, 67, 191, 94, 131, 236, 63, 0, 0, 0, 0, 198, 197, 199, 190, 190, 20, 251, 63, 0, 0, 0, 0, 46, 222, 204, 50, 0, 0, 0, 64, 0, 0, 0, 0, 200, 197, 199, 62, 190, 20, 251, 63, 0, 0, 0, 0, 27, 239, 67, 63, 93, 131, 236, 63, 0, 0, 0, 0, 215, 57, 142, 63, 51, 219, 212, 63, 0, 0, 0, 0, 242, 4, 181, 63, 245, 4, 181, 63, 0, 0, 0, 0, 49, 219, 212, 63, 219, 57, 142, 63, 0, 0, 0, 0, 95, 131, 236, 63, 21, 239, 67, 63, 0, 0, 0, 0, 191, 20, 251, 63, 188, 197, 199, 62, 0, 0, 0, 0)
|
||||
}]
|
||||
|
|
|
@ -373,6 +373,7 @@ func drop_object() -> void:
|
|||
|
||||
# let go of this object
|
||||
picked_up_object.let_go(
|
||||
self,
|
||||
_velocity_averager.linear_velocity() * impulse_factor,
|
||||
_velocity_averager.angular_velocity())
|
||||
picked_up_object = null
|
||||
|
@ -401,7 +402,7 @@ func _pick_up_object(target: Node3D) -> void:
|
|||
# Pick up our target. Note, target may do instant drop_and_free
|
||||
picked_up_ranged = not _object_in_grab_area.has(target)
|
||||
picked_up_object = target
|
||||
target.pick_up(self, _controller)
|
||||
target.pick_up(self)
|
||||
|
||||
# If object picked up then emit signal
|
||||
if is_instance_valid(picked_up_object):
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
|
||||
[node name="FunctionPickup" type="Node3D"]
|
||||
script = ExtResource("1")
|
||||
grab_collision_mask = 327684
|
||||
|
|
|
@ -81,11 +81,15 @@ func _on_area_entered(area : Area3D) -> void:
|
|||
pose_area,
|
||||
pose_area.pose_priority,
|
||||
pose_area.left_pose)
|
||||
# Disable grabpoints in this pose_area
|
||||
pose_area.disable_grab_points()
|
||||
elif _controller.tracker == "right_hand" and pose_area.right_pose:
|
||||
_hand.add_pose_override(
|
||||
pose_area,
|
||||
pose_area.pose_priority,
|
||||
pose_area.right_pose)
|
||||
# Disable grabpoints in this pose_area
|
||||
pose_area.disable_grab_points()
|
||||
|
||||
|
||||
## Signal handler called when this XRToolsFunctionPoseArea leaves an area
|
||||
|
@ -97,3 +101,6 @@ func _on_area_exited(area : Area3D) -> void:
|
|||
|
||||
# Remove any overrides set from this hand-pose area
|
||||
_hand.remove_pose_override(pose_area)
|
||||
|
||||
# Enable previously disabled grabpoints
|
||||
pose_area.enable_grab_points()
|
||||
|
|
|
@ -68,6 +68,12 @@ var _dominant : Node3D
|
|||
# Right controller
|
||||
@onready var _right_controller := XRHelpers.get_right_controller(self)
|
||||
|
||||
# Left collision hand
|
||||
@onready var _left_hand := XRToolsHand.find_left(self)
|
||||
|
||||
# Right collision hand
|
||||
@onready var _right_hand := XRToolsHand.find_right(self)
|
||||
|
||||
# Left collision hand
|
||||
@onready var _left_collision_hand := XRToolsCollisionHand.find_left(self)
|
||||
|
||||
|
@ -205,6 +211,8 @@ func _on_left_picked_up(what : Node3D) -> void:
|
|||
# If collision hands present then target the handle
|
||||
if _left_collision_hand:
|
||||
_left_collision_hand.add_target_override(_left_handle, 0)
|
||||
elif _left_hand:
|
||||
_left_hand.add_target_override(_left_handle, 0)
|
||||
|
||||
|
||||
## Handler for right controller picked up
|
||||
|
@ -225,6 +233,8 @@ func _on_right_picked_up(what : Node3D) -> void:
|
|||
# If collision hands present then target the handle
|
||||
if _right_collision_hand:
|
||||
_right_collision_hand.add_target_override(_right_handle, 0)
|
||||
elif _right_hand:
|
||||
_right_hand.add_target_override(_right_handle, 0)
|
||||
|
||||
|
||||
## Handler for left controller dropped
|
||||
|
@ -232,6 +242,8 @@ func _on_left_dropped() -> void:
|
|||
# If collision hands present then clear handle target
|
||||
if _left_collision_hand:
|
||||
_left_collision_hand.remove_target_override(_left_handle)
|
||||
if _left_hand:
|
||||
_left_hand.remove_target_override(_left_handle)
|
||||
|
||||
# Release handle and transfer dominance
|
||||
_left_handle = null
|
||||
|
@ -243,6 +255,8 @@ func _on_right_dropped() -> void:
|
|||
# If collision hands present then clear handle target
|
||||
if _right_collision_hand:
|
||||
_right_collision_hand.remove_target_override(_right_handle)
|
||||
if _right_hand:
|
||||
_right_hand.remove_target_override(_right_handle)
|
||||
|
||||
# Release handle and transfer dominance
|
||||
_right_handle = null
|
||||
|
|
|
@ -117,13 +117,21 @@ func _ready():
|
|||
_line.hide()
|
||||
|
||||
|
||||
# Update grapple display objects
|
||||
func _process(_delta: float):
|
||||
# Update the grappling line and target
|
||||
func _physics_process(_delta : float):
|
||||
# Skip if running in the editor
|
||||
if Engine.is_editor_hint():
|
||||
return
|
||||
|
||||
# Update grapple line
|
||||
# If pointing grappler at target then show the target
|
||||
if enabled and not is_active and _is_raycast_valid():
|
||||
_grapple_target.global_transform.origin = _grapple_raycast.get_collision_point()
|
||||
_grapple_target.global_transform = _grapple_target.global_transform.orthonormalized()
|
||||
_grapple_target.visible = true
|
||||
else:
|
||||
_grapple_target.visible = false
|
||||
|
||||
# If actively grappling then update and show the grappling line
|
||||
if is_active:
|
||||
var line_length := (hook_point - _controller.global_transform.origin).length()
|
||||
_line_helper.look_at(hook_point, Vector3.UP)
|
||||
|
@ -133,14 +141,6 @@ func _process(_delta: float):
|
|||
else:
|
||||
_line.visible = false
|
||||
|
||||
# Update grapple target
|
||||
if enabled and !is_active and _is_raycast_valid():
|
||||
_grapple_target.global_transform.origin = _grapple_raycast.get_collision_point()
|
||||
_grapple_target.global_transform = _grapple_target.global_transform.orthonormalized()
|
||||
_grapple_target.visible = true
|
||||
else:
|
||||
_grapple_target.visible = false
|
||||
|
||||
|
||||
# Perform grapple movement
|
||||
func physics_movement(delta: float, player_body: XRToolsPlayerBody, disabled: bool):
|
||||
|
@ -220,14 +220,12 @@ func _set_grappling(active: bool) -> void:
|
|||
|
||||
# Test if the raycast is striking a valid target
|
||||
func _is_raycast_valid() -> bool:
|
||||
# Fail if raycast not colliding
|
||||
if not _grapple_raycast.is_colliding():
|
||||
# Test if the raycast hit a collider
|
||||
var target = _grapple_raycast.get_collider()
|
||||
if not is_instance_valid(target):
|
||||
return false
|
||||
|
||||
# Get the target of the raycast
|
||||
var target : CollisionObject3D = _grapple_raycast.get_collider()
|
||||
|
||||
# Check tartget layer
|
||||
# Check collider layer
|
||||
return true if target.collision_layer & grapple_enable_mask else false
|
||||
|
||||
|
||||
|
|
156
addons/godot-xr-tools/functions/movement_jog.gd
Normal file
156
addons/godot-xr-tools/functions/movement_jog.gd
Normal file
|
@ -0,0 +1,156 @@
|
|||
@tool
|
||||
class_name XRToolsMovementJog
|
||||
extends XRToolsMovementProvider
|
||||
|
||||
|
||||
## XR Tools Movement Provider for Jog Movement
|
||||
##
|
||||
## This script provides jog-in-place movement for the player. This script
|
||||
## works with the [XRToolsPlayerBody] attached to the players [XROrigin3D].
|
||||
##
|
||||
## The implementation uses filtering of the controller Y velocities to measure
|
||||
## the approximate frequency of jog arm-swings; and uses that to
|
||||
## switch between stopped, slow, and fast movement speeds.
|
||||
|
||||
|
||||
## Speed mode enumeration
|
||||
enum SpeedMode {
|
||||
STOPPED, ## Not jogging
|
||||
SLOW, ## Jogging slowly
|
||||
FAST ## Jogging fast
|
||||
}
|
||||
|
||||
|
||||
## Jog arm-swing frequency in Hz to trigger slow movement
|
||||
const JOG_SLOW_FREQ := 3.5
|
||||
|
||||
## Jog arm-swing frequency in Hz to trigger fast movement
|
||||
const JOG_FAST_FREQ := 5.5
|
||||
|
||||
|
||||
## Movement provider order
|
||||
@export var order : int = 10
|
||||
|
||||
## Slow jogging speed in meters-per-second
|
||||
@export var slow_speed : float = 1.0
|
||||
|
||||
## Fast jogging speed in meters-per-second
|
||||
@export var fast_speed : float = 3.0
|
||||
|
||||
|
||||
# Jog arm-swing "stroke" detector "confidence-hat" signal
|
||||
var _conf_hat := 0.0
|
||||
|
||||
# Current jog arm-swing "stroke" duration
|
||||
var _current_stroke := 0.0
|
||||
|
||||
# Last jog arm-swing "stroke" total duration
|
||||
var _last_stroke := 0.0
|
||||
|
||||
# Current jog-speed mode
|
||||
var _speed_mode := SpeedMode.STOPPED
|
||||
|
||||
|
||||
# Left controller
|
||||
@onready var _left_controller := XRHelpers.get_left_controller(self)
|
||||
|
||||
# Right controller
|
||||
@onready var _right_controller := XRHelpers.get_right_controller(self)
|
||||
|
||||
|
||||
# Add support for is_xr_class on XRTools classes
|
||||
func is_xr_class(name : String) -> bool:
|
||||
return name == "XRToolsMovementJog" or super(name)
|
||||
|
||||
|
||||
# Perform jump movement
|
||||
func physics_movement(delta: float, player_body: XRToolsPlayerBody, _disabled: bool):
|
||||
# Skip if the either controller is inactive
|
||||
if !_left_controller.get_is_active() or !_right_controller.get_is_active():
|
||||
_speed_mode = SpeedMode.STOPPED
|
||||
return
|
||||
|
||||
# Get the arm-swing stroke frequency in Hz
|
||||
var freq := _get_stroke_frequency(delta)
|
||||
|
||||
# Transition between stopped/slow/fast speed-modes based on thresholds.
|
||||
# This thresholding has some hysteresis to make speed changes smoother.
|
||||
if freq == 0:
|
||||
_speed_mode = SpeedMode.STOPPED
|
||||
elif freq < JOG_SLOW_FREQ:
|
||||
_speed_mode = min(_speed_mode, SpeedMode.SLOW)
|
||||
elif freq < JOG_FAST_FREQ:
|
||||
_speed_mode = max(_speed_mode, SpeedMode.SLOW)
|
||||
else:
|
||||
_speed_mode = SpeedMode.FAST
|
||||
|
||||
# Pick the speed in meters-per-second based on the current speed-mode.
|
||||
var speed := 0.0
|
||||
if _speed_mode == SpeedMode.SLOW:
|
||||
speed = slow_speed
|
||||
elif _speed_mode == SpeedMode.FAST:
|
||||
speed = fast_speed
|
||||
|
||||
# Contribute to the player body speed - with clamping to the maximum speed
|
||||
player_body.ground_control_velocity.y += speed
|
||||
var length := player_body.ground_control_velocity.length()
|
||||
if length > fast_speed:
|
||||
player_body.ground_control_velocity *= fast_speed / length
|
||||
|
||||
|
||||
# Get the frequency of the last arm-swing "stroke" in Hz.
|
||||
func _get_stroke_frequency(delta : float) -> float:
|
||||
# Get the controller velocities
|
||||
var vl := _left_controller.get_pose().linear_velocity.y
|
||||
var vr := _right_controller.get_pose().linear_velocity.y
|
||||
|
||||
# Calculate the arm-swing "stroke" confidence. This is done by multiplying
|
||||
# the left and right controller vertical velocities. As these velocities
|
||||
# are highly anti-correlated while "jogging" the result is a confidence
|
||||
# signal with a high "peak" on every jog "stroke".
|
||||
var conf := vl * -vr
|
||||
|
||||
# Test for the confidence valley between strokes. This is used to signal
|
||||
# when to measure the duration between strokes.
|
||||
var valley := conf < _conf_hat
|
||||
|
||||
# Update confidence-hat. The confidence-hat signal has a fast-rise and
|
||||
# slow-decay. Rising with each jog arm-swing "stroke" and then taking time
|
||||
# to decay. The magnitude of the "confidence-hat" can be used as a good
|
||||
# indicator of when the user is jogging; and the difference between the
|
||||
# "confidence" and "confidence-hat" signals can be used to identify the
|
||||
# duration of a jog arm-swing "stroke".
|
||||
if valley:
|
||||
# Gently decay when in the confidence valley.
|
||||
_conf_hat = lerpf(_conf_hat, 0.0, delta * 2)
|
||||
else:
|
||||
# Quickly ramp confidence-hat to confidence
|
||||
_conf_hat = lerpf(_conf_hat, conf, delta * 20)
|
||||
|
||||
# If the "confidence-hat" signal is too low then the user is not jogging.
|
||||
# The stroke date-data is cleared and a stroke frequency of 0Hz is returned.
|
||||
if _conf_hat < 0.5:
|
||||
_current_stroke = 0.0
|
||||
_last_stroke = 0.0
|
||||
return 0.0
|
||||
|
||||
# Track the jog arm-swing "stroke" duration.
|
||||
if valley:
|
||||
# In the valley between jog arm-swing "strokes"
|
||||
_current_stroke += delta
|
||||
elif _current_stroke > 0.1:
|
||||
# Save the measured jog arm-swing "stroke" duration.
|
||||
_last_stroke = _current_stroke
|
||||
_current_stroke = 0.0
|
||||
|
||||
# If no previous jog arm-swing "stroke" duration to report, so return 0Hz.
|
||||
if _last_stroke < 0.1:
|
||||
return 0.0
|
||||
|
||||
# If the current jog arm-swing "stroke" is taking longer (slower) than 2Hz
|
||||
# then truncate to 0Hz.
|
||||
if _current_stroke > 0.75:
|
||||
return 0.0
|
||||
|
||||
# Return the last jog arm-swing "stroke" in Hz.
|
||||
return 1.0 / _last_stroke
|
6
addons/godot-xr-tools/functions/movement_jog.tscn
Normal file
6
addons/godot-xr-tools/functions/movement_jog.tscn
Normal file
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://chcuj3jysipk8"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/functions/movement_jog.gd" id="1_k4cao"]
|
||||
|
||||
[node name="MovementJog" type="Node" groups=["movement_providers"]]
|
||||
script = ExtResource("1_k4cao")
|
217
addons/godot-xr-tools/functions/movement_world_grab.gd
Normal file
217
addons/godot-xr-tools/functions/movement_world_grab.gd
Normal file
|
@ -0,0 +1,217 @@
|
|||
@tool
|
||||
class_name XRToolsMovementWorldGrab
|
||||
extends XRToolsMovementProvider
|
||||
|
||||
|
||||
## XR Tools Movement Provider for World-Grab
|
||||
##
|
||||
## This script provides world-grab movement for the player. To add world-grab
|
||||
## support, the player must also have [XRToolsFunctionPickup] nodes attached
|
||||
## to the left and right controllers, and an [XRToolsPlayerBody] under the
|
||||
## [XROrigin3D].
|
||||
##
|
||||
## World-Grab areas inherit from the world_grab_area scene, or be [Area3D]
|
||||
## nodes with the [XRToolsWorldGrabArea] script attached to them.
|
||||
|
||||
|
||||
## Signal invoked when the player starts world-grab movement
|
||||
signal player_world_grab_start
|
||||
|
||||
## Signal invoked when the player ends world-grab movement
|
||||
signal player_world_grab_end
|
||||
|
||||
|
||||
## Movement provider order
|
||||
@export var order : int = 15
|
||||
|
||||
## Smallest world scale
|
||||
@export var world_scale_min := 0.5
|
||||
|
||||
## Largest world scale
|
||||
@export var world_scale_max := 2.0
|
||||
|
||||
|
||||
# Left world-grab handle
|
||||
var _left_handle : Node3D
|
||||
|
||||
# Right world-grab handle
|
||||
var _right_handle : Node3D
|
||||
|
||||
|
||||
# Left pickup node
|
||||
@onready var _left_pickup_node := XRToolsFunctionPickup.find_left(self)
|
||||
|
||||
# Right pickup node
|
||||
@onready var _right_pickup_node := XRToolsFunctionPickup.find_right(self)
|
||||
|
||||
# Left controller
|
||||
@onready var _left_controller := XRHelpers.get_left_controller(self)
|
||||
|
||||
# Right controller
|
||||
@onready var _right_controller := XRHelpers.get_right_controller(self)
|
||||
|
||||
|
||||
# Add support for is_xr_class on XRTools classes
|
||||
func is_xr_class(name : String) -> bool:
|
||||
return name == "XRToolsMovementGrabWorld" or super(name)
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
# In Godot 4 we must now manually call our super class ready function
|
||||
super()
|
||||
|
||||
# Do not initialise if in the editor
|
||||
if Engine.is_editor_hint():
|
||||
return
|
||||
|
||||
# Connect pickup funcitons
|
||||
if _left_pickup_node.connect("has_picked_up", _on_left_picked_up):
|
||||
push_error("Unable to connect left picked up signal")
|
||||
if _right_pickup_node.connect("has_picked_up", _on_right_picked_up):
|
||||
push_error("Unable to connect right picked up signal")
|
||||
if _left_pickup_node.connect("has_dropped", _on_left_dropped):
|
||||
push_error("Unable to connect left dropped signal")
|
||||
if _right_pickup_node.connect("has_dropped", _on_right_dropped):
|
||||
push_error("Unable to connect right dropped signal")
|
||||
|
||||
|
||||
## Perform player physics movement
|
||||
func physics_movement(delta: float, player_body: XRToolsPlayerBody, disabled: bool):
|
||||
# Disable world-grab movement if requested
|
||||
if disabled or !enabled:
|
||||
_set_world_grab_moving(false)
|
||||
return
|
||||
|
||||
# Always set velocity to zero if enabled
|
||||
player_body.velocity = Vector3.ZERO
|
||||
|
||||
# Check for world-grab handles being deleted while held
|
||||
if not is_instance_valid(_left_handle):
|
||||
_left_handle = null
|
||||
if not is_instance_valid(_right_handle):
|
||||
_right_handle = null
|
||||
|
||||
# Disable world-grab movement if not holding the world
|
||||
if not _left_handle and not _right_handle:
|
||||
_set_world_grab_moving(false)
|
||||
return
|
||||
|
||||
# World grabbed
|
||||
_set_world_grab_moving(true)
|
||||
|
||||
# Handle world-grab movement
|
||||
var offset := Vector3.ZERO
|
||||
if _left_handle and not _right_handle:
|
||||
# Left-hand movement only
|
||||
var left_pickup_pos := _left_controller.global_position
|
||||
var left_grab_pos := _left_handle.global_position
|
||||
offset = left_pickup_pos - left_grab_pos
|
||||
elif _right_handle and not _left_handle:
|
||||
# Right-hand movement only
|
||||
var right_pickup_pos := _right_controller.global_position
|
||||
var right_grab_pos := _right_handle.global_position
|
||||
offset = right_pickup_pos - right_grab_pos
|
||||
else:
|
||||
# Get the world-grab handle positions
|
||||
var left_grab_pos := _left_handle.global_position
|
||||
var right_grab_pos := _right_handle.global_position
|
||||
var grab_l2r := (right_grab_pos - left_grab_pos).slide(player_body.up_player)
|
||||
var grab_mid := (left_grab_pos + right_grab_pos) * 0.5
|
||||
|
||||
# Get the pickup positions
|
||||
var left_pickup_pos := _left_controller.global_position
|
||||
var right_pickup_pos := _right_controller.global_position
|
||||
var pickup_l2r := (right_pickup_pos - left_pickup_pos).slide(player_body.up_player)
|
||||
var pickup_mid := (left_pickup_pos + right_pickup_pos) * 0.5
|
||||
|
||||
# Apply rotation
|
||||
var angle := grab_l2r.signed_angle_to(pickup_l2r, player_body.up_player)
|
||||
player_body.rotate_player(angle)
|
||||
|
||||
# Apply scale
|
||||
var new_world_scale := XRServer.world_scale * grab_l2r.length() / pickup_l2r.length()
|
||||
new_world_scale = clamp(new_world_scale, world_scale_min, world_scale_max)
|
||||
XRServer.world_scale = new_world_scale
|
||||
|
||||
# Apply offset
|
||||
offset = pickup_mid - grab_mid
|
||||
|
||||
# Move the player by the offset
|
||||
var old_position := player_body.global_position
|
||||
player_body.move_body(-offset / delta)
|
||||
player_body.velocity = Vector3.ZERO
|
||||
#player_body.move_and_collide(-offset)
|
||||
|
||||
# Report exclusive motion performed (to bypass gravity)
|
||||
return true
|
||||
|
||||
|
||||
## Start or stop world-grab movement
|
||||
func _set_world_grab_moving(active: bool) -> void:
|
||||
# Skip if no change
|
||||
if active == is_active:
|
||||
return
|
||||
|
||||
# Update state
|
||||
is_active = active
|
||||
|
||||
# Handle state change
|
||||
if is_active:
|
||||
emit_signal("player_world_grab_start")
|
||||
else:
|
||||
emit_signal("player_world_grab_end")
|
||||
|
||||
|
||||
## Handler for left controller picked up
|
||||
func _on_left_picked_up(what : Node3D) -> void:
|
||||
# Get the world-grab area
|
||||
var world_grab_area = what as XRToolsWorldGrabArea
|
||||
if not world_grab_area:
|
||||
return
|
||||
|
||||
# Get the handle
|
||||
_left_handle = world_grab_area.get_grab_handle(_left_pickup_node)
|
||||
if not _left_handle:
|
||||
return
|
||||
|
||||
|
||||
## Handler for right controller picked up
|
||||
func _on_right_picked_up(what : Node3D) -> void:
|
||||
# Get the world-grab area
|
||||
var world_grab_area = what as XRToolsWorldGrabArea
|
||||
if not world_grab_area:
|
||||
return
|
||||
|
||||
# Get the handle
|
||||
_right_handle = world_grab_area.get_grab_handle(_right_pickup_node)
|
||||
if not _right_handle:
|
||||
return
|
||||
|
||||
|
||||
## Handler for left controller dropped
|
||||
func _on_left_dropped() -> void:
|
||||
# Release handle and transfer dominance
|
||||
_left_handle = null
|
||||
|
||||
|
||||
## Handler for righ controller dropped
|
||||
func _on_right_dropped() -> void:
|
||||
# Release handle and transfer dominance
|
||||
_right_handle = null
|
||||
|
||||
|
||||
# This method verifies the movement provider has a valid configuration.
|
||||
func _get_configuration_warnings() -> PackedStringArray:
|
||||
var warnings := super()
|
||||
|
||||
# Verify the left controller pickup
|
||||
if !XRToolsFunctionPickup.find_left(self):
|
||||
warnings.append("Unable to find left XRToolsFunctionPickup node")
|
||||
|
||||
# Verify the right controller pickup
|
||||
if !XRToolsFunctionPickup.find_right(self):
|
||||
warnings.append("Unable to find right XRToolsFunctionPickup node")
|
||||
|
||||
# Return warnings
|
||||
return warnings
|
6
addons/godot-xr-tools/functions/movement_world_grab.tscn
Normal file
6
addons/godot-xr-tools/functions/movement_world_grab.tscn
Normal file
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://dg3gr6ofd8yx4"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/functions/movement_world_grab.gd" id="1_0qp8q"]
|
||||
|
||||
[node name="MovementWorldGrab" type="Node" groups=["movement_providers"]]
|
||||
script = ExtResource("1_0qp8q")
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b55738edba8fcdaab47c5e40cf4b900b10c86ea67f9d40dc041f84f4e76ec484
|
||||
oid sha256:ec74b5b5948e76d01115d7ff959610515e97aca1c42870f36b4a747f2dc4cb70
|
||||
size 2416
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3a3e64d9a45c8ab58180b00eae7ed8e306c22686656fca4ed854b87283ed4c09
|
||||
oid sha256:46cdd3222390fdf4b7e6f591958bbf30944df088a71cab919ba54a49ace2baf8
|
||||
size 2424
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
[remap]
|
||||
|
||||
importer="keep"
|
|
@ -0,0 +1,3 @@
|
|||
[remap]
|
||||
|
||||
importer="keep"
|
3
addons/godot-xr-tools/hands/blend/hand_l.blend.import
Normal file
3
addons/godot-xr-tools/hands/blend/hand_l.blend.import
Normal file
|
@ -0,0 +1,3 @@
|
|||
[remap]
|
||||
|
||||
importer="keep"
|
3
addons/godot-xr-tools/hands/blend/hand_r.blend.import
Normal file
3
addons/godot-xr-tools/hands/blend/hand_r.blend.import
Normal file
|
@ -0,0 +1,3 @@
|
|||
[remap]
|
||||
|
||||
importer="keep"
|
|
@ -79,8 +79,10 @@ func _ready():
|
|||
if Engine.is_editor_hint():
|
||||
return
|
||||
|
||||
# Disconnect from parent transform, as we move to it in the physics step
|
||||
# Disconnect from parent transform as we move to it in the physics step,
|
||||
# and boost the physics priority above any grab-drivers or hands.
|
||||
top_level = true
|
||||
process_physics_priority = -90
|
||||
|
||||
# Populate nodes
|
||||
_controller = XRTools.find_xr_ancestor(self, "*", "XRController3D")
|
||||
|
@ -171,6 +173,7 @@ func _move_to_target():
|
|||
# Orient the hand then move
|
||||
global_transform.basis = _target.global_transform.basis
|
||||
move_and_slide(_target.global_position - global_position)
|
||||
force_update_transform()
|
||||
|
||||
|
||||
# This function inserts a target override into the overrides list by priority
|
||||
|
|
|
@ -41,6 +41,9 @@ var _last_world_scale : float = 1.0
|
|||
var _controller : XRController3D
|
||||
|
||||
## Initial hand transform (from controller) - used for scaling hands
|
||||
var _initial_transform : Transform3D
|
||||
|
||||
## Current hand transform (from controller) - after scale
|
||||
var _transform : Transform3D
|
||||
|
||||
## Hand mesh
|
||||
|
@ -64,6 +67,12 @@ var _force_grip := -1.0
|
|||
## Force trigger value (< 0 for no force)
|
||||
var _force_trigger := -1.0
|
||||
|
||||
# Sorted stack of TargetOverride
|
||||
var _target_overrides := []
|
||||
|
||||
# Current target (controller or override)
|
||||
var _target : Node3D
|
||||
|
||||
|
||||
## Pose-override class
|
||||
class PoseOverride:
|
||||
|
@ -83,6 +92,20 @@ class PoseOverride:
|
|||
settings = s
|
||||
|
||||
|
||||
## Target-override class
|
||||
class TargetOverride:
|
||||
## Target of the override
|
||||
var target : Node3D
|
||||
|
||||
## Target priority
|
||||
var priority : int
|
||||
|
||||
## Target-override constructor
|
||||
func _init(t : Node3D, p : int):
|
||||
target = t
|
||||
priority = p
|
||||
|
||||
|
||||
# Add support for is_xr_class on XRTools classes
|
||||
func is_xr_class(name : String) -> bool:
|
||||
return name == "XRToolsHand"
|
||||
|
@ -91,7 +114,15 @@ func is_xr_class(name : String) -> bool:
|
|||
## Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
# Save the initial hand transform
|
||||
_transform = transform
|
||||
_initial_transform = transform
|
||||
_transform = _initial_transform
|
||||
|
||||
# Disconnect from parent transform as we move to it in the physics step,
|
||||
# and boost the physics priority after any grab-drivers but before other
|
||||
# processing.
|
||||
if not Engine.is_editor_hint():
|
||||
top_level = true
|
||||
process_physics_priority = -70
|
||||
|
||||
# Find our controller
|
||||
_controller = XRTools.find_xr_ancestor(self, "*", "XRController3D")
|
||||
|
@ -105,12 +136,13 @@ func _ready() -> void:
|
|||
_update_hand_blend_tree()
|
||||
_update_hand_material_override()
|
||||
_update_pose()
|
||||
_update_target()
|
||||
|
||||
|
||||
## This method is called on every frame. It checks for world-scale changes and
|
||||
## scales itself causing the hand mesh and skeleton to scale appropriately.
|
||||
## It then reads the grip and trigger action values to animate the hand.
|
||||
func _process(_delta: float) -> void:
|
||||
## This method checks for world-scale changes and scales itself causing the
|
||||
## hand mesh and skeleton to scale appropriately. It then reads the grip and
|
||||
## trigger action values to animate the hand.
|
||||
func _physics_process(_delta: float) -> void:
|
||||
# Do not run physics if in the editor
|
||||
if Engine.is_editor_hint():
|
||||
return
|
||||
|
@ -118,7 +150,7 @@ func _process(_delta: float) -> void:
|
|||
# Scale the hand mesh with the world scale.
|
||||
if XRServer.world_scale != _last_world_scale:
|
||||
_last_world_scale = XRServer.world_scale
|
||||
transform = _transform.scaled(Vector3.ONE * _last_world_scale)
|
||||
_transform = _initial_transform.scaled(Vector3.ONE * _last_world_scale)
|
||||
emit_signal("hand_scale_changed", _last_world_scale)
|
||||
|
||||
# Animate the hand mesh with the controller inputs
|
||||
|
@ -133,6 +165,9 @@ func _process(_delta: float) -> void:
|
|||
$AnimationTree.set("parameters/Grip/blend_amount", grip)
|
||||
$AnimationTree.set("parameters/Trigger/blend_amount", trigger)
|
||||
|
||||
# Move to target
|
||||
global_transform = _target.global_transform * _transform
|
||||
force_update_transform()
|
||||
|
||||
|
||||
# This method verifies the hand has a valid configuration.
|
||||
|
@ -161,7 +196,7 @@ func _get_configuration_warnings() -> PackedStringArray:
|
|||
## Find an [XRToolsHand] node.
|
||||
##
|
||||
## This function searches from the specified node for an [XRToolsHand] assuming
|
||||
## the node is a sibling of the hand under an [ARVRController].
|
||||
## the node is a sibling of the hand under an [XROrigin3D].
|
||||
static func find_instance(node : Node) -> XRToolsHand:
|
||||
return XRTools.find_xr_child(
|
||||
XRHelpers.get_xr_controller(node),
|
||||
|
@ -169,6 +204,24 @@ static func find_instance(node : Node) -> XRToolsHand:
|
|||
"XRToolsHand") as XRToolsHand
|
||||
|
||||
|
||||
## This function searches from the specified node for the left controller
|
||||
## [XRToolsHand] assuming the node is a sibling of the [XROrigin3D].
|
||||
static func find_left(node : Node) -> XRToolsHand:
|
||||
return XRTools.find_xr_child(
|
||||
XRHelpers.get_left_controller(node),
|
||||
"*",
|
||||
"XRToolsHand") as XRToolsHand
|
||||
|
||||
|
||||
## This function searches from the specified node for the right controller
|
||||
## [XRToolsHand] assuming the node is a sibling of the [XROrigin3D].
|
||||
static func find_right(node : Node) -> XRToolsHand:
|
||||
return XRTools.find_xr_child(
|
||||
XRHelpers.get_right_controller(node),
|
||||
"*",
|
||||
"XRToolsHand") as XRToolsHand
|
||||
|
||||
|
||||
## Set the blend tree
|
||||
func set_hand_blend_tree(blend_tree : AnimationNodeBlendTree) -> void:
|
||||
hand_blend_tree = blend_tree
|
||||
|
@ -227,6 +280,32 @@ func force_grip_trigger(grip : float = -1.0, trigger : float = -1.0) -> void:
|
|||
if trigger >= 0.0: $AnimationTree.set("parameters/Trigger/blend_amount", trigger)
|
||||
|
||||
|
||||
## This function adds a target override. The collision hand will attempt to
|
||||
## move to the highest priority target, or the [XRController3D] if no override
|
||||
## is specified.
|
||||
func add_target_override(target : Node3D, priority : int) -> void:
|
||||
# Remove any existing target override from this source
|
||||
var modified := _remove_target_override(target)
|
||||
|
||||
# Insert the target override
|
||||
_insert_target_override(target, priority)
|
||||
modified = true
|
||||
|
||||
# Update the target
|
||||
if modified:
|
||||
_update_target()
|
||||
|
||||
|
||||
## This function remove a target override.
|
||||
func remove_target_override(target : Node3D) -> void:
|
||||
# Remove the target override
|
||||
var modified := _remove_target_override(target)
|
||||
|
||||
# Update the pose
|
||||
if modified:
|
||||
_update_target()
|
||||
|
||||
|
||||
func _update_hand_blend_tree() -> void:
|
||||
# As we're going to make modifications to our animation tree, we need to do
|
||||
# a deep copy, simply setting resource local to scene does not seem to be enough
|
||||
|
@ -329,6 +408,59 @@ func _remove_pose_override(who : Node) -> bool:
|
|||
return modified
|
||||
|
||||
|
||||
# This function inserts a target override into the overrides list by priority
|
||||
# order.
|
||||
func _insert_target_override(target : Node3D, priority : int) -> void:
|
||||
# Construct the target override
|
||||
var override := TargetOverride.new(target, priority)
|
||||
|
||||
# Iterate over all target overrides in the list
|
||||
for pos in _target_overrides.size():
|
||||
# Get the target override
|
||||
var o : TargetOverride = _target_overrides[pos]
|
||||
|
||||
# Insert as early as possible to not invalidate sorting
|
||||
if o.priority <= priority:
|
||||
_target_overrides.insert(pos, override)
|
||||
return
|
||||
|
||||
# Insert at the end
|
||||
_target_overrides.push_back(override)
|
||||
|
||||
|
||||
# This function removes a target from the overrides list
|
||||
func _remove_target_override(target : Node) -> bool:
|
||||
var pos := 0
|
||||
var length := _target_overrides.size()
|
||||
var modified := false
|
||||
|
||||
# Iterate over all pose overrides in the list
|
||||
while pos < length:
|
||||
# Get the target override
|
||||
var o : TargetOverride = _target_overrides[pos]
|
||||
|
||||
# Check for a match
|
||||
if o.target == target:
|
||||
# Remove the override
|
||||
_target_overrides.remove_at(pos)
|
||||
modified = true
|
||||
length -= 1
|
||||
else:
|
||||
# Advance down the list
|
||||
pos += 1
|
||||
|
||||
# Return the modified indicator
|
||||
return modified
|
||||
|
||||
|
||||
# This function updates the target for hand movement.
|
||||
func _update_target() -> void:
|
||||
if _target_overrides.size():
|
||||
_target = _target_overrides[0].target
|
||||
else:
|
||||
_target = get_parent()
|
||||
|
||||
|
||||
static func _find_child(node : Node, type : String) -> Node:
|
||||
# Iterate through all children
|
||||
for child in node.get_children():
|
||||
|
|
|
@ -55,6 +55,10 @@ func is_xr_class(name : String) -> bool:
|
|||
# Called when the node enters the scene tree. This constructs the physics-bone
|
||||
# nodes and performs initial positioning.
|
||||
func _ready():
|
||||
# Skip if in the editor
|
||||
if Engine.is_editor_hint():
|
||||
return
|
||||
|
||||
# Connect the 'hand_scale_changed' signal
|
||||
var physics_hand := XRToolsHand.find_instance(self) as XRToolsPhysicsHand
|
||||
if physics_hand:
|
||||
|
@ -102,6 +106,10 @@ func _ready():
|
|||
# Called during the physics process and moves the physics-bone to follow the
|
||||
# skeletal-bone.
|
||||
func _physics_process(delta: float) -> void:
|
||||
# Skip if in the editor
|
||||
if Engine.is_editor_hint():
|
||||
return
|
||||
|
||||
_move_bone(delta)
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://bd7h22w1o77fp"
|
||||
uid="uid://bu07alt6vkbaq"
|
||||
path="res://.godot/imported/Hand_Glove_L.gltf-ac6c06fe48ca0d7ce0f9faffd177a897.scn"
|
||||
|
||||
[deps]
|
||||
|
@ -22,7 +22,6 @@ meshes/generate_lods=true
|
|||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
|
@ -30,5 +29,4 @@ animation/trimming=false
|
|||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://iwqh6hhdhhdk"
|
||||
uid="uid://w7th3d2hl7b5"
|
||||
path="res://.godot/imported/Hand_Glove_R.gltf-0e99922c663867da8d37af9597ab1ce8.scn"
|
||||
|
||||
[deps]
|
||||
|
@ -22,7 +22,6 @@ meshes/generate_lods=true
|
|||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
|
@ -30,5 +29,4 @@ animation/trimming=false
|
|||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://dokq2yjsxpofc"
|
||||
uid="uid://bnx4hithcij6y"
|
||||
path="res://.godot/imported/Hand_Glove_low_L.gltf-7b94b12c0dff159d494da6cafd52895d.scn"
|
||||
|
||||
[deps]
|
||||
|
@ -22,7 +22,6 @@ meshes/generate_lods=true
|
|||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
|
@ -30,5 +29,4 @@ animation/trimming=false
|
|||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://cacrvwhji2ibw"
|
||||
uid="uid://csgsp0wuw8ucy"
|
||||
path="res://.godot/imported/Hand_Glove_low_R.gltf-c32907596b2287c95aff0e704780ef3d.scn"
|
||||
|
||||
[deps]
|
||||
|
@ -22,7 +22,6 @@ meshes/generate_lods=true
|
|||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
|
@ -30,5 +29,4 @@ animation/trimming=false
|
|||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://bh786yhm5v4fh"
|
||||
uid="uid://q1l3fknstir2"
|
||||
path="res://.godot/imported/Hand_Nails_L.gltf-22452b307072e9d363b1f547e2b6a365.scn"
|
||||
|
||||
[deps]
|
||||
|
@ -22,7 +22,6 @@ meshes/generate_lods=true
|
|||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
|
@ -30,5 +29,4 @@ animation/trimming=false
|
|||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://duffm8pu8ask7"
|
||||
uid="uid://c6s5nvekg0isa"
|
||||
path="res://.godot/imported/Hand_Nails_R.gltf-35869d6a39400588d95465aa5e3b528d.scn"
|
||||
|
||||
[deps]
|
||||
|
@ -22,7 +22,6 @@ meshes/generate_lods=true
|
|||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
|
@ -30,5 +29,4 @@ animation/trimming=false
|
|||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://w87o4l6qhsmd"
|
||||
uid="uid://c4nba0qpi0uls"
|
||||
path="res://.godot/imported/Hand_Nails_low_L.gltf-60d8096917582bfe1d760ff1ad173fc8.scn"
|
||||
|
||||
[deps]
|
||||
|
@ -22,7 +22,6 @@ meshes/generate_lods=true
|
|||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
|
@ -30,5 +29,4 @@ animation/trimming=false
|
|||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://cgobg2isk3rk1"
|
||||
uid="uid://dunu03tc5vdbh"
|
||||
path="res://.godot/imported/Hand_Nails_low_R.gltf-7d9fc9507def4b4fd9c10cdae7aa6e11.scn"
|
||||
|
||||
[deps]
|
||||
|
@ -22,7 +22,6 @@ meshes/generate_lods=true
|
|||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
|
@ -30,5 +29,4 @@ animation/trimming=false
|
|||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://g510kgsy5u72"
|
||||
uid="uid://16colgxrw27d"
|
||||
path="res://.godot/imported/Hand_low_L.gltf-a83bdf9115e4fb62c63deabade61cbbb.scn"
|
||||
|
||||
[deps]
|
||||
|
@ -22,7 +22,6 @@ meshes/generate_lods=true
|
|||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
|
@ -30,5 +29,4 @@ animation/trimming=false
|
|||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://c6rnlihkm44f0"
|
||||
uid="uid://cjrac51wst3tu"
|
||||
path="res://.godot/imported/Hand_low_R.gltf-8b164aff014e5c5bfa2eccc8e40e7e97.scn"
|
||||
|
||||
[deps]
|
||||
|
@ -22,7 +22,6 @@ meshes/generate_lods=true
|
|||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
|
@ -30,5 +29,4 @@ animation/trimming=false
|
|||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://dvkh1gxbhwri4"
|
||||
uid="uid://dhaqth6q5yw4n"
|
||||
path="res://.godot/imported/hand_l.gltf-6ba1595ac4c28aef3719b7f0b4f2f4f2.scn"
|
||||
|
||||
[deps]
|
||||
|
@ -22,7 +22,6 @@ meshes/generate_lods=true
|
|||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
|
@ -30,5 +29,4 @@ animation/trimming=false
|
|||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://ytv5cbt6dbeg"
|
||||
uid="uid://ds1t8vc0kxoeo"
|
||||
path="res://.godot/imported/hand_r.gltf-dd429687cadefbc3e7a21ae26addfb30.scn"
|
||||
|
||||
[deps]
|
||||
|
@ -22,7 +22,6 @@ meshes/generate_lods=true
|
|||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
|
@ -30,5 +29,4 @@ animation/trimming=false
|
|||
animation/remove_immutable_tracks=true
|
||||
import_script/path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=0
|
||||
gltf/embedded_image_handling=1
|
||||
|
|
|
@ -5,11 +5,10 @@
|
|||
[sub_resource type="BoxShape3D" id="BoxShape3D_bv7in"]
|
||||
size = Vector3(0.045, 0.075, 0.1)
|
||||
|
||||
[node name="CollisionHandLeft" type="StaticBody3D"]
|
||||
process_priority = -90
|
||||
process_physics_priority = -90
|
||||
[node name="CollisionHandLeft" type="AnimatableBody3D"]
|
||||
collision_layer = 131072
|
||||
collision_mask = 327711
|
||||
sync_to_physics = false
|
||||
script = ExtResource("1_t5acd")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
|
|
|
@ -5,11 +5,10 @@
|
|||
[sub_resource type="BoxShape3D" id="BoxShape3D_fc2ij"]
|
||||
size = Vector3(0.045, 0.075, 0.1)
|
||||
|
||||
[node name="CollisionHandRight" type="StaticBody3D"]
|
||||
process_priority = -90
|
||||
process_physics_priority = -90
|
||||
[node name="CollisionHandRight" type="AnimatableBody3D"]
|
||||
collision_layer = 131072
|
||||
collision_mask = 327711
|
||||
sync_to_physics = false
|
||||
script = ExtResource("1_so3hf")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=13 format=3 uid="uid://bpdj5njb8nhot"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://the6y7swe6j0" path="res://addons/godot-xr-tools/hands/animations/left/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://dvkh1gxbhwri4" path="res://addons/godot-xr-tools/hands/model/hand_l.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://dhaqth6q5yw4n" path="res://addons/godot-xr-tools/hands/model/hand_l.gltf" 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_x4lr3"]
|
||||
[ext_resource type="Material" uid="uid://ba02jnd2dswyn" path="res://addons/godot-xr-tools/hands/materials/cleaning_glove.material" id="4"]
|
||||
|
@ -36,7 +36,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_rtx6p")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_y01rx")
|
||||
nodes/Trigger/position = Vector2(-360, 20)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="LeftHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=14 format=3 uid="uid://nqiyqnx42m61"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://dvkh1gxbhwri4" path="res://addons/godot-xr-tools/hands/model/hand_l.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://dhaqth6q5yw4n" path="res://addons/godot-xr-tools/hands/model/hand_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/physics_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_0aa1r"]
|
||||
|
@ -37,7 +37,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_g5ps2")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_v8isy")
|
||||
nodes/Trigger/position = Vector2(-360, 20)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="LeftPhysicsHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
[gd_scene load_steps=13 format=3 uid="uid://njx823gyk04n"]
|
||||
|
||||
[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://q1l3fknstir2" 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_e6byy"]
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_x12eo"]
|
||||
animation = &"Grip"
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_bs8g1"]
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_kw2gg"]
|
||||
animation = &"Grip"
|
||||
|
||||
[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_675c4"]
|
||||
[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_o8j0s"]
|
||||
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_2ssci"]
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_cxcnq"]
|
||||
animation = &"Grip 5"
|
||||
|
||||
[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_narw6"]
|
||||
[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_yn70n"]
|
||||
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_wp4n0"]
|
||||
[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_v8owg"]
|
||||
graph_offset = Vector2(-536, 11)
|
||||
nodes/ClosedHand1/node = SubResource("AnimationNodeAnimation_e6byy")
|
||||
nodes/ClosedHand1/node = SubResource("AnimationNodeAnimation_x12eo")
|
||||
nodes/ClosedHand1/position = Vector2(-600, 300)
|
||||
nodes/ClosedHand2/node = SubResource("AnimationNodeAnimation_bs8g1")
|
||||
nodes/ClosedHand2/node = SubResource("AnimationNodeAnimation_kw2gg")
|
||||
nodes/ClosedHand2/position = Vector2(-360, 300)
|
||||
nodes/Grip/node = SubResource("AnimationNodeBlend2_675c4")
|
||||
nodes/Grip/node = SubResource("AnimationNodeBlend2_o8j0s")
|
||||
nodes/Grip/position = Vector2(0, 20)
|
||||
nodes/OpenHand/node = SubResource("AnimationNodeAnimation_2ssci")
|
||||
nodes/OpenHand/node = SubResource("AnimationNodeAnimation_cxcnq")
|
||||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_narw6")
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_yn70n")
|
||||
nodes/Trigger/position = Vector2(-360, 20)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="LeftHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
@ -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_wp4n0")
|
||||
tree_root = SubResource("AnimationNodeBlendTree_v8owg")
|
||||
anim_player = NodePath("../Hand_Nails_L/AnimationPlayer")
|
||||
active = true
|
||||
parameters/Grip/blend_amount = 0.0
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=14 format=3 uid="uid://cy03d57iyrci"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://the6y7swe6j0" path="res://addons/godot-xr-tools/hands/animations/left/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://bh786yhm5v4fh" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_L.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://q1l3fknstir2" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_L.gltf" id="2"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/physics_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_fye1l"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/hand_physics_bone.gd" id="4"]
|
||||
|
@ -37,7 +37,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_40ncn")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_fjpy6")
|
||||
nodes/Trigger/position = Vector2(-360, 20)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="LeftPhysicsHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=14 format=3 uid="uid://ddsj74hpt1kgb"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bd7h22w1o77fp" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_L.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://bu07alt6vkbaq" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_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="AnimationNodeBlendTree" uid="uid://dl8yf7ipqotd1" path="res://addons/godot-xr-tools/hands/animations/left/hand_blend_tree.tres" id="3"]
|
||||
[ext_resource type="Resource" uid="uid://dertgu7k8alls" path="res://addons/godot-xr-tools/hands/poses/pose_default_left.tres" id="3_rnhp7"]
|
||||
|
@ -37,7 +37,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_2ih7n")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_02eq5")
|
||||
nodes/Trigger/position = Vector2(-360, 20)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="LeftPhysicsHand" type="Node3D"]
|
||||
script = ExtResource("6")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=13 format=3 uid="uid://hpr0v012ghsb"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bd7h22w1o77fp" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_L.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://bu07alt6vkbaq" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_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_s33di"]
|
||||
|
@ -36,7 +36,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_kjpaa")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_kisbg")
|
||||
nodes/Trigger/position = Vector2(-360, 20)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="LeftHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=13 format=3 uid="uid://d1tl07geqm5xq"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://ytv5cbt6dbeg" path="res://addons/godot-xr-tools/hands/model/hand_r.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://ds1t8vc0kxoeo" path="res://addons/godot-xr-tools/hands/model/hand_r.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://bxipj7hyjwy6f" path="res://addons/godot-xr-tools/hands/animations/right/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://dmpjtk0l8vh6v" path="res://addons/godot-xr-tools/hands/poses/pose_default_right.tres" id="3_xmpie"]
|
||||
|
@ -36,7 +36,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_gm5ny")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_3o6s4")
|
||||
nodes/Trigger/position = Vector2(-360, 40)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="RightHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=14 format=3 uid="uid://cigx2gnf4tg4d"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://ytv5cbt6dbeg" path="res://addons/godot-xr-tools/hands/model/hand_r.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://ds1t8vc0kxoeo" path="res://addons/godot-xr-tools/hands/model/hand_r.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://bxipj7hyjwy6f" path="res://addons/godot-xr-tools/hands/animations/right/AnimationPlayer.tscn" id="2"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/physics_hand.gd" id="3"]
|
||||
[ext_resource type="Resource" uid="uid://dmpjtk0l8vh6v" path="res://addons/godot-xr-tools/hands/poses/pose_default_right.tres" id="3_23oai"]
|
||||
|
@ -37,7 +37,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_4mwbe")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_x7ees")
|
||||
nodes/Trigger/position = Vector2(-360, 40)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="RightPhysicsHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=13 format=3 uid="uid://raeeicvvindd"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://duffm8pu8ask7" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_R.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://c6s5nvekg0isa" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_R.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://bxipj7hyjwy6f" path="res://addons/godot-xr-tools/hands/animations/right/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://dmpjtk0l8vh6v" path="res://addons/godot-xr-tools/hands/poses/pose_default_right.tres" id="3_lydk3"]
|
||||
|
@ -36,7 +36,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_0hd6d")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_okkj6")
|
||||
nodes/Trigger/position = Vector2(-360, 40)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="RightHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=14 format=3 uid="uid://kcqomcjq52np"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bxipj7hyjwy6f" path="res://addons/godot-xr-tools/hands/animations/right/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://duffm8pu8ask7" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_R.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://c6s5nvekg0isa" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_R.gltf" id="2"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/physics_hand.gd" id="3"]
|
||||
[ext_resource type="Resource" uid="uid://dmpjtk0l8vh6v" path="res://addons/godot-xr-tools/hands/poses/pose_default_right.tres" id="3_gqplw"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/hand_physics_bone.gd" id="4"]
|
||||
|
@ -37,7 +37,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_4bb4h")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_b8ks0")
|
||||
nodes/Trigger/position = Vector2(-360, 40)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="RightPhysicsHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=14 format=3 uid="uid://b6xesntm4qeo5"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bxipj7hyjwy6f" path="res://addons/godot-xr-tools/hands/animations/right/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://iwqh6hhdhhdk" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_R.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://w7th3d2hl7b5" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_R.gltf" id="2"]
|
||||
[ext_resource type="AnimationNodeBlendTree" uid="uid://m85b1gogdums" path="res://addons/godot-xr-tools/hands/animations/right/hand_blend_tree.tres" id="3"]
|
||||
[ext_resource type="Resource" uid="uid://dmpjtk0l8vh6v" path="res://addons/godot-xr-tools/hands/poses/pose_default_right.tres" id="3_h0fv3"]
|
||||
[ext_resource type="Material" uid="uid://dy4ya7w0k18ds" path="res://addons/godot-xr-tools/hands/materials/glove_caucasian_dark_camo.material" id="4"]
|
||||
|
@ -37,7 +37,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_dc0m1")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_guoth")
|
||||
nodes/Trigger/position = Vector2(-360, 40)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="RightPhysicsHand" type="Node3D"]
|
||||
script = ExtResource("6")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=13 format=3 uid="uid://dup2vp8v5rpi5"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bxipj7hyjwy6f" path="res://addons/godot-xr-tools/hands/animations/right/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://iwqh6hhdhhdk" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_R.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://w7th3d2hl7b5" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_R.gltf" id="2"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/hand.gd" id="3"]
|
||||
[ext_resource type="Resource" uid="uid://dmpjtk0l8vh6v" path="res://addons/godot-xr-tools/hands/poses/pose_default_right.tres" id="3_3ih8a"]
|
||||
[ext_resource type="AnimationNodeBlendTree" uid="uid://m85b1gogdums" path="res://addons/godot-xr-tools/hands/animations/right/hand_blend_tree.tres" id="4"]
|
||||
|
@ -36,7 +36,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_4vdom")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_hef27")
|
||||
nodes/Trigger/position = Vector2(-360, 40)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="RightHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=13 format=3 uid="uid://bq86r4yll8po"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://the6y7swe6j0" path="res://addons/godot-xr-tools/hands/animations/left/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://g510kgsy5u72" path="res://addons/godot-xr-tools/hands/model/Hand_low_L.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://16colgxrw27d" path="res://addons/godot-xr-tools/hands/model/Hand_low_L.gltf" 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_wyae6"]
|
||||
[ext_resource type="AnimationNodeBlendTree" uid="uid://dl8yf7ipqotd1" path="res://addons/godot-xr-tools/hands/animations/left/hand_blend_tree.tres" id="5"]
|
||||
|
@ -36,7 +36,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_470u2")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_fhgyt")
|
||||
nodes/Trigger/position = Vector2(-360, 20)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="LeftHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=13 format=3 uid="uid://b4kad2kuba1yn"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://w87o4l6qhsmd" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_low_L.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://c4nba0qpi0uls" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_low_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_ry7qg"]
|
||||
|
@ -36,7 +36,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_c3h37")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_ihxeh")
|
||||
nodes/Trigger/position = Vector2(-360, 20)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="LeftHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=14 format=3 uid="uid://b8hc2ex21u8xj"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://g510kgsy5u72" path="res://addons/godot-xr-tools/hands/model/Hand_low_L.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://16colgxrw27d" path="res://addons/godot-xr-tools/hands/model/Hand_low_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/physics_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_4017m"]
|
||||
|
@ -37,7 +37,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_fvmpw")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_a1c3t")
|
||||
nodes/Trigger/position = Vector2(-360, 20)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="LeftPhysicsHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=14 format=3 uid="uid://bdwmserhqai5h"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://the6y7swe6j0" path="res://addons/godot-xr-tools/hands/animations/left/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://w87o4l6qhsmd" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_low_L.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://c4nba0qpi0uls" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_low_L.gltf" id="2"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/physics_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_t17lq"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/hand_physics_bone.gd" id="4"]
|
||||
|
@ -37,7 +37,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_3l13i")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_ms3kw")
|
||||
nodes/Trigger/position = Vector2(-360, 20)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="LeftPhysicsHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=14 format=3 uid="uid://bj1aas6kty3qx"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://the6y7swe6j0" path="res://addons/godot-xr-tools/hands/animations/left/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://dokq2yjsxpofc" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_low_L.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://bnx4hithcij6y" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_low_L.gltf" id="2"]
|
||||
[ext_resource type="AnimationNodeBlendTree" uid="uid://dl8yf7ipqotd1" path="res://addons/godot-xr-tools/hands/animations/left/hand_blend_tree.tres" id="3"]
|
||||
[ext_resource type="Resource" uid="uid://dertgu7k8alls" path="res://addons/godot-xr-tools/hands/poses/pose_default_left.tres" id="3_oehre"]
|
||||
[ext_resource type="Material" uid="uid://dy4ya7w0k18ds" path="res://addons/godot-xr-tools/hands/materials/glove_caucasian_dark_camo.material" id="4"]
|
||||
|
@ -37,7 +37,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_vkt4w")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_1yhw8")
|
||||
nodes/Trigger/position = Vector2(-360, 20)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="LeftPhysicsHand" type="Node3D"]
|
||||
script = ExtResource("6")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=13 format=3 uid="uid://bx1xdisoqo1f6"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://dokq2yjsxpofc" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_low_L.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://bnx4hithcij6y" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_low_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_iq5xt"]
|
||||
|
@ -36,7 +36,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_csu2l")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_akg52")
|
||||
nodes/Trigger/position = Vector2(-360, 20)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="LeftHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=13 format=3 uid="uid://xqimcf20s2jp"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bxipj7hyjwy6f" path="res://addons/godot-xr-tools/hands/animations/right/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://c6rnlihkm44f0" path="res://addons/godot-xr-tools/hands/model/Hand_low_R.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://cjrac51wst3tu" path="res://addons/godot-xr-tools/hands/model/Hand_low_R.gltf" id="2"]
|
||||
[ext_resource type="Material" uid="uid://ba02jnd2dswyn" path="res://addons/godot-xr-tools/hands/materials/cleaning_glove.material" id="3"]
|
||||
[ext_resource type="Resource" uid="uid://dmpjtk0l8vh6v" path="res://addons/godot-xr-tools/hands/poses/pose_default_right.tres" id="3_r4xyu"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/hand.gd" id="4"]
|
||||
|
@ -36,7 +36,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_l50hj")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_vrc3g")
|
||||
nodes/Trigger/position = Vector2(-360, 40)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="RightHand" type="Node3D"]
|
||||
script = ExtResource("4")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=13 format=3 uid="uid://l2n30mpbkdyw"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bxipj7hyjwy6f" path="res://addons/godot-xr-tools/hands/animations/right/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://cgobg2isk3rk1" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_low_R.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://dunu03tc5vdbh" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_low_R.gltf" id="2"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/hand.gd" id="3"]
|
||||
[ext_resource type="Resource" uid="uid://dmpjtk0l8vh6v" path="res://addons/godot-xr-tools/hands/poses/pose_default_right.tres" id="3_f67ka"]
|
||||
[ext_resource type="Material" uid="uid://dbvge3quu3bju" path="res://addons/godot-xr-tools/hands/materials/caucasian_hand.material" id="4"]
|
||||
|
@ -36,7 +36,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_covtt")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_h5uio")
|
||||
nodes/Trigger/position = Vector2(-360, 40)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="RightHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=14 format=3 uid="uid://bkdeegb8w3oah"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bxipj7hyjwy6f" path="res://addons/godot-xr-tools/hands/animations/right/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://c6rnlihkm44f0" path="res://addons/godot-xr-tools/hands/model/Hand_low_R.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://cjrac51wst3tu" path="res://addons/godot-xr-tools/hands/model/Hand_low_R.gltf" id="2"]
|
||||
[ext_resource type="Material" uid="uid://bhiiya7ow6h8v" path="res://addons/godot-xr-tools/hands/materials/labglove.material" id="3"]
|
||||
[ext_resource type="Resource" uid="uid://dmpjtk0l8vh6v" path="res://addons/godot-xr-tools/hands/poses/pose_default_right.tres" id="3_e8slj"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/physics_hand.gd" id="4"]
|
||||
|
@ -37,7 +37,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_1fjc2")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_ai2qv")
|
||||
nodes/Trigger/position = Vector2(-360, 40)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="RightPhysicsHand" type="Node3D"]
|
||||
script = ExtResource("4")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=14 format=3 uid="uid://btf05hjpw6k05"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bxipj7hyjwy6f" path="res://addons/godot-xr-tools/hands/animations/right/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://cgobg2isk3rk1" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_low_R.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://dunu03tc5vdbh" path="res://addons/godot-xr-tools/hands/model/Hand_Nails_low_R.gltf" id="2"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/physics_hand.gd" id="3"]
|
||||
[ext_resource type="Resource" uid="uid://dmpjtk0l8vh6v" path="res://addons/godot-xr-tools/hands/poses/pose_default_right.tres" id="3_b86a5"]
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/hands/hand_physics_bone.gd" id="4"]
|
||||
|
@ -37,7 +37,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_l0mk4")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_it0su")
|
||||
nodes/Trigger/position = Vector2(-360, 40)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="RightPhysicsHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=14 format=3 uid="uid://c2uvwvdlsfuep"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://bxipj7hyjwy6f" path="res://addons/godot-xr-tools/hands/animations/right/AnimationPlayer.tscn" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://cacrvwhji2ibw" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_low_R.gltf" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://csgsp0wuw8ucy" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_low_R.gltf" id="2"]
|
||||
[ext_resource type="AnimationNodeBlendTree" uid="uid://m85b1gogdums" path="res://addons/godot-xr-tools/hands/animations/right/hand_blend_tree.tres" id="3"]
|
||||
[ext_resource type="Resource" uid="uid://dmpjtk0l8vh6v" path="res://addons/godot-xr-tools/hands/poses/pose_default_right.tres" id="3_xodao"]
|
||||
[ext_resource type="Material" uid="uid://dy4ya7w0k18ds" path="res://addons/godot-xr-tools/hands/materials/glove_caucasian_dark_camo.material" id="4"]
|
||||
|
@ -37,7 +37,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_8kdoe")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_5qnsq")
|
||||
nodes/Trigger/position = Vector2(-360, 40)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="RightPhysicsHand" type="Node3D"]
|
||||
script = ExtResource("6")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=13 format=3 uid="uid://chumpejwiub7f"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://cacrvwhji2ibw" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_low_R.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://csgsp0wuw8ucy" path="res://addons/godot-xr-tools/hands/model/Hand_Glove_low_R.gltf" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://bxipj7hyjwy6f" path="res://addons/godot-xr-tools/hands/animations/right/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://dmpjtk0l8vh6v" path="res://addons/godot-xr-tools/hands/poses/pose_default_right.tres" id="3_2wryo"]
|
||||
|
@ -36,7 +36,7 @@ nodes/OpenHand/node = SubResource("AnimationNodeAnimation_4o3a2")
|
|||
nodes/OpenHand/position = Vector2(-600, 100)
|
||||
nodes/Trigger/node = SubResource("AnimationNodeBlend2_5v4fm")
|
||||
nodes/Trigger/position = Vector2(-360, 40)
|
||||
node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"]
|
||||
node_connections = [&"output", 0, &"Grip", &"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1"]
|
||||
|
||||
[node name="RightHand" type="Node3D"]
|
||||
script = ExtResource("3")
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bcgvvpllho2e1"
|
||||
uid="uid://cs7m7m0k2506g"
|
||||
path="res://.godot/imported/african_baseColor.png-c1a63b2c85973a5f7673482d994697e9.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bbegc1t6sypfe"
|
||||
uid="uid://dk8o82rjww802"
|
||||
path="res://.godot/imported/african_realistic_baseColor.png-67cf0f3230115c16edbeaf7b76430f7c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ura2vjsqegjt"
|
||||
uid="uid://c506svon268ms"
|
||||
path.s3tc="res://.godot/imported/caucasian_baseColor.png-2ffa4b91e9a1b3bcc11c22eccd941be7.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/caucasian_baseColor.png-2ffa4b91e9a1b3bcc11c22eccd941be7.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dphwanfi4jxrk"
|
||||
uid="uid://n1xq4cm67o07"
|
||||
path="res://.godot/imported/caucasian_realistic_baseColor.png-6d28d56c1e76917b749358861074492c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://deh22migllf4t"
|
||||
uid="uid://dv711ytktesj2"
|
||||
path.s3tc="res://.godot/imported/cleaning_glove_baseColor.png-775896445d04c5f9ecad1dcd0609e336.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/cleaning_glove_baseColor.png-775896445d04c5f9ecad1dcd0609e336.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c2hanl27i7oc1"
|
||||
uid="uid://cocorrka3dtq3"
|
||||
path="res://.godot/imported/glove_african_dark_camo.png-3a526d8d251e73995f6fd3ba5cdd0b4e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -2,26 +2,28 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://vfkxkijr37rm"
|
||||
path="res://.godot/imported/glove_african_green_camo.png-b4a9e045aac0313108230034e03317fd.ctex"
|
||||
uid="uid://bidphehpipwhg"
|
||||
path.s3tc="res://.godot/imported/glove_african_green_camo.png-b4a9e045aac0313108230034e03317fd.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/glove_african_green_camo.png-b4a9e045aac0313108230034e03317fd.etc2.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
"imported_formats": ["s3tc_bptc", "etc2_astc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/godot-xr-tools/hands/textures/glove_african_green_camo.png"
|
||||
dest_files=["res://.godot/imported/glove_african_green_camo.png-b4a9e045aac0313108230034e03317fd.ctex"]
|
||||
dest_files=["res://.godot/imported/glove_african_green_camo.png-b4a9e045aac0313108230034e03317fd.s3tc.ctex", "res://.godot/imported/glove_african_green_camo.png-b4a9e045aac0313108230034e03317fd.etc2.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
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=false
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
|
@ -31,4 +33,4 @@ process/normal_map_invert_y=false
|
|||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
detect_3d/compress_to=0
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://daphmv2yp22x"
|
||||
uid="uid://c7jutkax2fd1k"
|
||||
path.s3tc="res://.godot/imported/glove_caucasian_dark_camo.png-338e35680a2de0f7c6ad596eba6a3d5f.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/glove_caucasian_dark_camo.png-338e35680a2de0f7c6ad596eba6a3d5f.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bvbbghjfsau1b"
|
||||
uid="uid://dgkfppran5j1f"
|
||||
path.s3tc="res://.godot/imported/glove_caucasian_green_camo.png-009f6b98bc0f9d73ac78a6b6900a0d00.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/glove_caucasian_green_camo.png-009f6b98bc0f9d73ac78a6b6900a0d00.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://duqdr6qqrim0s"
|
||||
uid="uid://bw8rmigwt5pr4"
|
||||
path.s3tc="res://.godot/imported/glove_fingerless_normal.png-46736b8f0a977e37b17257f7bbbb718f.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/glove_fingerless_normal.png-46736b8f0a977e37b17257f7bbbb718f.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://3fax6yglkrd3"
|
||||
uid="uid://d2iocwfr47kqp"
|
||||
path.s3tc="res://.godot/imported/glove_fingerless_occlusionRoughnessMetallic.png-441bf1f84442c3cd6ae3834c9c982565.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/glove_fingerless_occlusionRoughnessMetallic.png-441bf1f84442c3cd6ae3834c9c982565.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dasjkfath7rqu"
|
||||
uid="uid://dt6k4nuvpo38o"
|
||||
path.s3tc="res://.godot/imported/glove_normal.png-da82759e655cb7106cb0172b7076b948.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/glove_normal.png-da82759e655cb7106cb0172b7076b948.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b5v1xfnkyjaf6"
|
||||
uid="uid://yslwgnpbpeen"
|
||||
path.s3tc="res://.godot/imported/glove_occlusionRoughnessMetallic.png-1a61c4638e30c81daa59d92c8681eb2c.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/glove_occlusionRoughnessMetallic.png-1a61c4638e30c81daa59d92c8681eb2c.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dlkn0p2k7gfqc"
|
||||
uid="uid://b6tgv6ucbgv3r"
|
||||
path="res://.godot/imported/hands_normal.png-291c7217751274bfe1199e3de899450f.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dy5hyp5n7o6gl"
|
||||
uid="uid://h3sjbnu6uplb"
|
||||
path.s3tc="res://.godot/imported/hands_occlusionRoughnessMetallic.png-73229fc54301aa8833117ebde8abfd4e.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/hands_occlusionRoughnessMetallic.png-73229fc54301aa8833117ebde8abfd4e.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cxwjhfe1yvm65"
|
||||
uid="uid://d4gbpgjwjuovb"
|
||||
path.s3tc="res://.godot/imported/labglove_baseColor.png-2eb9fa4d9955a5755a96f0663ee3ceb2.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/labglove_baseColor.png-2eb9fa4d9955a5755a96f0663ee3ceb2.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b8a7ol64q60tb"
|
||||
uid="uid://bcll0cv3rie0i"
|
||||
path="res://.godot/imported/icon.png-1d8efcc4c33e64800e22ea3150ef148d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ciimvkgy0mee0"
|
||||
uid="uid://8s03ra8tp0hr"
|
||||
path.s3tc="res://.godot/imported/ring.png-34d9c9e9780f2732148a5b14fcac48dd.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/ring.png-34d9c9e9780f2732148a5b14fcac48dd.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bbfwq7mhqgwjm"
|
||||
uid="uid://ddoj6c345cb0c"
|
||||
path.s3tc="res://.godot/imported/teleport_arrow.png-f1bd44b6f478277692b3fa29171b62d3.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/teleport_arrow.png-f1bd44b6f478277692b3fa29171b62d3.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cygfooytyfhyd"
|
||||
uid="uid://cu4j1s8qr1rjq"
|
||||
path.s3tc="res://.godot/imported/teleport_target.png-cd812f7d5692711ac91f6c8a4753ad73.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/teleport_target.png-cd812f7d5692711ac91f6c8a4753ad73.etc2.ctex"
|
||||
metadata={
|
||||
|
|
|
@ -47,29 +47,29 @@ func _ready() -> void:
|
|||
# Called on every frame when the handle is held to check for snapping
|
||||
func _process(_delta: float) -> void:
|
||||
# Skip if not picked up
|
||||
if !picked_up_by:
|
||||
if not is_picked_up():
|
||||
return
|
||||
|
||||
# If too far from the origin then drop the handle
|
||||
var origin_pos = handle_origin.global_transform.origin
|
||||
var handle_pos = global_transform.origin
|
||||
if handle_pos.distance_to(origin_pos) > snap_distance:
|
||||
picked_up_by.drop_object()
|
||||
drop()
|
||||
|
||||
|
||||
# Called when the handle is picked up
|
||||
func pick_up(by, with_controller) -> void:
|
||||
func pick_up(by) -> void:
|
||||
# Call the base-class to perform the pickup
|
||||
super(by, with_controller)
|
||||
super(by)
|
||||
|
||||
# Enable the process function while held
|
||||
set_process(true)
|
||||
|
||||
|
||||
# Called when the handle is dropped
|
||||
func let_go(_p_linear_velocity: Vector3, _p_angular_velocity: Vector3) -> void:
|
||||
func let_go(by: Node3D, _p_linear_velocity: Vector3, _p_angular_velocity: Vector3) -> void:
|
||||
# Call the base-class to perform the drop, but with no velocity
|
||||
super(Vector3.ZERO, Vector3.ZERO)
|
||||
super(by, Vector3.ZERO, Vector3.ZERO)
|
||||
|
||||
# Disable the process function as no-longer held
|
||||
set_process(false)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://bwqiturebyt3h"]
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/interactables/interactable_hinge.gd" id="1"]
|
||||
[ext_resource path="res://addons/godot-xr-tools/interactables/interactable_hinge.gd" type="Script" id=1]
|
||||
|
||||
[node name="InteractableHinge" type="Spatial"]
|
||||
script = ExtResource("1")
|
||||
script = ExtResource( 1 )
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://cnfk38alyp72q"]
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/interactables/interactable_joystick.gd" id="1"]
|
||||
[ext_resource path="res://addons/godot-xr-tools/interactables/interactable_joystick.gd" type="Script" id=1]
|
||||
|
||||
[node name="InteractableJoystick" type="Spatial"]
|
||||
script = ExtResource("1")
|
||||
script = ExtResource( 1 )
|
||||
|
|
|
@ -10,9 +10,9 @@ resource_local_to_scene = true
|
|||
render_priority = 0
|
||||
shader = ExtResource("2")
|
||||
shader_parameter/albedo = Color(1, 1, 1, 1)
|
||||
shader_parameter/value = 0.2
|
||||
shader_parameter/fade = 0.05
|
||||
shader_parameter/radius = 0.8
|
||||
shader_parameter/value = 0.2
|
||||
shader_parameter/width = 0.2
|
||||
|
||||
[node name="HoldButton" type="Node3D"]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[gd_scene load_steps=8 format=3 uid="uid://cjccb67fjl4aw"]
|
||||
[gd_scene load_steps=8 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/godot-xr-tools/misc/vr_common_shader_cache.gd" id="1"]
|
||||
[ext_resource type="Material" uid="uid://bk72wfw25ff0v" path="res://addons/godot-xr-tools/materials/teleport.tres" id="2_6822k"]
|
||||
[ext_resource type="Material" path="res://addons/godot-xr-tools/materials/teleport.tres" id="2_6822k"]
|
||||
[ext_resource type="Material" path="res://addons/godot-xr-tools/materials/target.tres" id="3_agvdv"]
|
||||
[ext_resource type="Material" path="res://addons/godot-xr-tools/materials/capsule.tres" id="4_gxjsg"]
|
||||
[ext_resource type="Material" path="res://addons/godot-xr-tools/materials/pointer.tres" id="5_12251"]
|
||||
|
|
|
@ -15,8 +15,15 @@ extends Node3D
|
|||
## If true, the grip control must be held to keep holding the climbable
|
||||
var press_to_hold : bool = true
|
||||
|
||||
## Dictionary of temporary grab-handles indexed by the pickup node.
|
||||
var grab_locations := {}
|
||||
|
||||
## Array of permanent grab points.
|
||||
var _grab_points : Array[XRToolsGrabPoint] = []
|
||||
|
||||
## Dictionary of temporary grabs keyed by the pickup node
|
||||
var _grab_temps : Dictionary = {}
|
||||
|
||||
## Dictionary of active grabs keyed by the pickup node
|
||||
var _grabs : Dictionary = {}
|
||||
|
||||
|
||||
# Add support for is_xr_class on XRTools classes
|
||||
|
@ -24,41 +31,79 @@ func is_xr_class(name : String) -> bool:
|
|||
return name == "XRToolsClimbable"
|
||||
|
||||
|
||||
# Called when the node becomes "ready"
|
||||
func _ready() -> void:
|
||||
# Get all grab points
|
||||
for child in get_children():
|
||||
var grab_point := child as XRToolsGrabPoint
|
||||
if grab_point:
|
||||
_grab_points.push_back(grab_point)
|
||||
|
||||
|
||||
# Called by XRToolsFunctionPickup
|
||||
func is_picked_up() -> bool:
|
||||
return false
|
||||
|
||||
|
||||
func can_pick_up(_by: Node3D) -> bool:
|
||||
return true
|
||||
|
||||
|
||||
# Called by XRToolsFunctionPickup when user presses the action button while holding this object
|
||||
func action():
|
||||
pass
|
||||
|
||||
|
||||
# Ignore highlighting requests from XRToolsFunctionPickup
|
||||
func request_highlight(_from, _on) -> void:
|
||||
pass
|
||||
|
||||
|
||||
# Called by XRToolsFunctionPickup when this is picked up by a controller
|
||||
func pick_up(by: Node3D, _with_controller: XRController3D) -> void:
|
||||
# Get the ID to save the grab handle under
|
||||
var id = by.get_instance_id()
|
||||
func pick_up(by: Node3D) -> void:
|
||||
# Get the best permanent grab-point
|
||||
var point := _get_grab_point(by)
|
||||
if not point:
|
||||
# Get a temporary grab-point for the pickup
|
||||
point = _grab_temps.get(by)
|
||||
if not point:
|
||||
# Create a new temporary grab-point childed to the climbable
|
||||
point = Node3D.new()
|
||||
add_child(point)
|
||||
_grab_temps[by] = point
|
||||
|
||||
# Get or construct the grab handle
|
||||
var handle = grab_locations.get(id)
|
||||
if not handle:
|
||||
handle = Node3D.new()
|
||||
add_child(handle)
|
||||
grab_locations[id] = handle
|
||||
# Set the temporary to the current positon
|
||||
point.global_transform = by.global_transform
|
||||
|
||||
# Save the grab
|
||||
_grabs[by] = point
|
||||
|
||||
# Set the handles global transform. As it's a child of this
|
||||
# climbable it will move as the climbable moves
|
||||
handle.global_transform = by.global_transform
|
||||
|
||||
# Called by XRToolsFunctionPickup when this is let go by a controller
|
||||
func let_go(_p_linear_velocity: Vector3, _p_angular_velocity: Vector3) -> void:
|
||||
pass
|
||||
func let_go(by: Node3D, _p_linear_velocity: Vector3, _p_angular_velocity: Vector3) -> void:
|
||||
_grabs.erase(by);
|
||||
|
||||
|
||||
# Get the grab handle
|
||||
func get_grab_handle(p: Node3D) -> Node3D:
|
||||
return grab_locations.get(p.get_instance_id())
|
||||
func get_grab_handle(by: Node3D) -> Node3D:
|
||||
return _grabs.get(by)
|
||||
|
||||
|
||||
## Find the most suitable grab-point for the grabber
|
||||
func _get_grab_point(by : Node3D) -> Node3D:
|
||||
# Find the best grab-point
|
||||
var fitness := 0.0
|
||||
var point : XRToolsGrabPoint = null
|
||||
for p in _grab_points:
|
||||
var f := p.can_grab(by, null)
|
||||
if f > fitness:
|
||||
fitness = f
|
||||
point = p
|
||||
|
||||
# Resolve redirection
|
||||
while point is XRToolsGrabPointRedirect:
|
||||
point = point.target
|
||||
|
||||
# Return the best grab point
|
||||
print_verbose("%s> picked grab-point %s" % [name, point])
|
||||
return point
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
@tool
|
||||
class_name XRToolsForceBody
|
||||
extends StaticBody3D
|
||||
extends AnimatableBody3D
|
||||
|
||||
|
||||
## XRTools Force Body script
|
||||
##
|
||||
## This script enhances StaticBody3D with move_and_slide and the ability
|
||||
## This script enhances AnimatableBody3D with move_and_slide and the ability
|
||||
## to push bodies by emparting forces on them.
|
||||
|
||||
|
||||
|
@ -42,6 +42,9 @@ func is_xr_class(name : String) -> bool:
|
|||
## This function moves and slides along the [param move] vector. It returns
|
||||
## information about the last collision, or null if no collision
|
||||
func move_and_slide(move : Vector3) -> ForceBodyCollision:
|
||||
# Make sure this is off or weird shit happens...
|
||||
sync_to_physics = false
|
||||
|
||||
# Loop performing the movement steps
|
||||
var step_move := move
|
||||
var ret : ForceBodyCollision = null
|
||||
|
|
171
addons/godot-xr-tools/objects/grab_points/grab.gd
Normal file
171
addons/godot-xr-tools/objects/grab_points/grab.gd
Normal file
|
@ -0,0 +1,171 @@
|
|||
class_name Grab
|
||||
extends Grabber
|
||||
|
||||
|
||||
## Grab Class
|
||||
##
|
||||
## This class encodes information about an active grab. Additionally it applies
|
||||
## hand poses and collision exceptions as appropriate.
|
||||
|
||||
|
||||
## Priority for grip poses
|
||||
const GRIP_POSE_PRIORITY := 100
|
||||
|
||||
## Priority for grip targeting
|
||||
const GRIP_TARGET_PRIORITY := 100
|
||||
|
||||
|
||||
## Grab target
|
||||
var what : XRToolsPickable
|
||||
|
||||
## Grab point information
|
||||
var point : XRToolsGrabPoint
|
||||
|
||||
## Hand grab point information
|
||||
var hand_point : XRToolsGrabPointHand
|
||||
|
||||
## Grab transform
|
||||
var transform : Transform3D
|
||||
|
||||
## Position drive strength
|
||||
var drive_position : float = 1.0
|
||||
|
||||
## Angle drive strength
|
||||
var drive_angle : float = 1.0
|
||||
|
||||
## Aim drive strength
|
||||
var drive_aim : float = 0.0
|
||||
|
||||
## Has target arrived at grab point
|
||||
var _arrived : bool = false
|
||||
|
||||
|
||||
## Initialize the grab
|
||||
func _init(
|
||||
p_grabber : Grabber,
|
||||
p_what : XRToolsPickable,
|
||||
p_point : XRToolsGrabPoint,
|
||||
p_precise : bool) -> void:
|
||||
|
||||
# Copy the grabber information
|
||||
by = p_grabber.by
|
||||
pickup = p_grabber.pickup
|
||||
controller = p_grabber.controller
|
||||
hand = p_grabber.hand
|
||||
collision_hand = p_grabber.collision_hand
|
||||
|
||||
# Set the point
|
||||
what = p_what
|
||||
point = p_point
|
||||
hand_point = p_point as XRToolsGrabPointHand
|
||||
|
||||
# Calculate the grab transform
|
||||
if p_point:
|
||||
transform = p_point.transform
|
||||
elif p_precise:
|
||||
transform = p_what.global_transform.inverse() * by.global_transform
|
||||
else:
|
||||
transform = Transform3D.IDENTITY
|
||||
|
||||
# Set the drive parameters
|
||||
if hand_point:
|
||||
drive_position = hand_point.drive_position
|
||||
drive_angle = hand_point.drive_angle
|
||||
drive_aim = hand_point.drive_aim
|
||||
|
||||
# Apply collision exceptions
|
||||
if collision_hand:
|
||||
what.add_collision_exception_with(collision_hand)
|
||||
collision_hand.add_collision_exception_with(what)
|
||||
|
||||
|
||||
## Set the target as arrived at the grab-point
|
||||
func set_arrived() -> void:
|
||||
# Ignore if already arrived
|
||||
if _arrived:
|
||||
return
|
||||
|
||||
# Set arrived and apply any hand pose
|
||||
print_verbose("%s> arrived at %s" % [what.name, point])
|
||||
_arrived = true
|
||||
_set_hand_pose()
|
||||
|
||||
# Report the grab
|
||||
print_verbose("%s> grabbed by %s", [what.name, by.name])
|
||||
what.grabbed.emit(what, by)
|
||||
|
||||
|
||||
## Set the grab point
|
||||
func set_grab_point(p_point : XRToolsGrabPoint) -> void:
|
||||
# Skip if no change
|
||||
if p_point == point:
|
||||
return
|
||||
|
||||
# Remove any current pose override
|
||||
_clear_hand_pose()
|
||||
|
||||
# Update the grab point
|
||||
point = p_point
|
||||
hand_point = point as XRToolsGrabPointHand
|
||||
|
||||
# Update the transform
|
||||
if point:
|
||||
transform = point.transform
|
||||
|
||||
# Apply the new hand grab-point settings
|
||||
if hand_point:
|
||||
drive_position = hand_point.drive_position
|
||||
drive_angle = hand_point.drive_angle
|
||||
drive_aim = hand_point.drive_aim
|
||||
|
||||
# Apply any pose overrides
|
||||
if _arrived:
|
||||
_set_hand_pose()
|
||||
|
||||
# Report switch
|
||||
print_verbose("%s> switched grab point to %s", [what.name, point.name])
|
||||
what.released.emit(what, by)
|
||||
what.grabbed.emit(what, by)
|
||||
|
||||
|
||||
## Release the grip
|
||||
func release() -> void:
|
||||
# Clear any hand pose
|
||||
_clear_hand_pose()
|
||||
|
||||
# Remove collision exceptions
|
||||
if is_instance_valid(collision_hand):
|
||||
what.remove_collision_exception_with(collision_hand)
|
||||
collision_hand.remove_collision_exception_with(what)
|
||||
|
||||
# Report the release
|
||||
print_verbose("%s> released by %s", [what.name, by.name])
|
||||
what.released.emit(what, by)
|
||||
|
||||
|
||||
# Set hand-pose overrides
|
||||
func _set_hand_pose() -> void:
|
||||
# Skip if not hand
|
||||
if not is_instance_valid(hand) or not is_instance_valid(hand_point):
|
||||
return
|
||||
|
||||
# Apply the hand-pose
|
||||
if hand_point.hand_pose:
|
||||
hand.add_pose_override(hand_point, GRIP_POSE_PRIORITY, hand_point.hand_pose)
|
||||
|
||||
# Apply hand snapping
|
||||
if hand_point.snap_hand:
|
||||
hand.add_target_override(hand_point, GRIP_TARGET_PRIORITY)
|
||||
|
||||
|
||||
# Clear any hand-pose overrides
|
||||
func _clear_hand_pose() -> void:
|
||||
# Skip if not hand
|
||||
if not is_instance_valid(hand) or not is_instance_valid(hand_point):
|
||||
return
|
||||
|
||||
# Remove hand-pose
|
||||
hand.remove_pose_override(hand_point)
|
||||
|
||||
# Remove hand snapping
|
||||
hand.remove_target_override(hand_point)
|
216
addons/godot-xr-tools/objects/grab_points/grab_driver.gd
Normal file
216
addons/godot-xr-tools/objects/grab_points/grab_driver.gd
Normal file
|
@ -0,0 +1,216 @@
|
|||
class_name XRToolsGrabDriver
|
||||
extends RemoteTransform3D
|
||||
|
||||
|
||||
## Grab state
|
||||
enum State {
|
||||
LERP,
|
||||
SNAP,
|
||||
}
|
||||
|
||||
|
||||
## Drive state
|
||||
var state : State = State.SNAP
|
||||
|
||||
## Target pickable
|
||||
var target : XRToolsPickable
|
||||
|
||||
## Primary grab information
|
||||
var primary : Grab = null
|
||||
|
||||
## Secondary grab information
|
||||
var secondary : Grab = null
|
||||
|
||||
## Lerp start position
|
||||
var lerp_start : Transform3D
|
||||
|
||||
## Lerp total duration
|
||||
var lerp_duration : float = 1.0
|
||||
|
||||
## Lerp time
|
||||
var lerp_time : float = 0.0
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _physics_process(delta : float) -> void:
|
||||
# Skip if no primary node
|
||||
if not is_instance_valid(primary):
|
||||
return
|
||||
|
||||
# Set destination from primary grab
|
||||
var destination := primary.by.global_transform * primary.transform.inverse()
|
||||
|
||||
# If present, apply secondary-node contributions
|
||||
if is_instance_valid(secondary):
|
||||
# Calculate lerp coefficients based on drive strengths
|
||||
var position_lerp := _vote(primary.drive_position, secondary.drive_position)
|
||||
var angle_lerp := _vote(primary.drive_angle, secondary.drive_angle)
|
||||
|
||||
# Calculate the transform from secondary grab
|
||||
var x1 := destination
|
||||
var x2 := secondary.by.global_transform * secondary.transform.inverse()
|
||||
|
||||
# Independently lerp the angle and position
|
||||
destination = Transform3D(
|
||||
x1.basis.slerp(x2.basis, angle_lerp),
|
||||
x1.origin.lerp(x2.origin, position_lerp))
|
||||
|
||||
# Test if we need to apply aiming
|
||||
if secondary.drive_aim > 0.0:
|
||||
# Convert destination from global to primary-local
|
||||
destination = primary.by.global_transform.inverse() * destination
|
||||
|
||||
# Calculate the from and to vectors in primary-local space
|
||||
var secondary_from := destination * secondary.transform.origin
|
||||
var secondary_to := primary.by.to_local(secondary.by.global_position)
|
||||
|
||||
# Build shortest arc
|
||||
secondary_from = secondary_from.normalized()
|
||||
secondary_to = secondary_to.normalized()
|
||||
var spherical := Quaternion(secondary_from, secondary_to)
|
||||
|
||||
# Build aim-rotation
|
||||
var rotate := Basis.IDENTITY.slerp(Basis(spherical), secondary.drive_aim)
|
||||
destination = Transform3D(rotate, Vector3.ZERO) * destination
|
||||
|
||||
# Convert destination from primary-local to global
|
||||
destination = primary.by.global_transform * destination
|
||||
|
||||
# Handle update
|
||||
match state:
|
||||
State.LERP:
|
||||
# Progress the lerp
|
||||
lerp_time += delta
|
||||
if lerp_time < lerp_duration:
|
||||
# Interpolate from lerp_start to destination
|
||||
destination = lerp_start.interpolate_with(
|
||||
destination,
|
||||
lerp_time / lerp_duration)
|
||||
else:
|
||||
# Lerp completed
|
||||
state = State.SNAP
|
||||
if primary: primary.set_arrived()
|
||||
if secondary: secondary.set_arrived()
|
||||
|
||||
# Apply the destination transform
|
||||
global_transform = destination
|
||||
force_update_transform()
|
||||
if is_instance_valid(target):
|
||||
target.force_update_transform()
|
||||
|
||||
|
||||
## Set the secondary grab point
|
||||
func add_grab(p_grab : Grab) -> void:
|
||||
# Set the secondary grab
|
||||
if p_grab.hand_point and p_grab.hand_point.mode == XRToolsGrabPointHand.Mode.PRIMARY:
|
||||
print_verbose("%s> new primary grab %s" % [target.name, p_grab.by.name])
|
||||
secondary = primary
|
||||
primary = p_grab
|
||||
else:
|
||||
print_verbose("%s> new secondary grab %s" % [target.name, p_grab.by.name])
|
||||
secondary = p_grab
|
||||
|
||||
# If snapped then report arrived at the new grab
|
||||
if state == State.SNAP:
|
||||
p_grab.set_arrived()
|
||||
|
||||
|
||||
## Get the grab information for the grab node
|
||||
func get_grab(by : Node3D) -> Grab:
|
||||
if primary and primary.by == by:
|
||||
return primary
|
||||
|
||||
if secondary and secondary.by == by:
|
||||
return secondary
|
||||
|
||||
return null
|
||||
|
||||
|
||||
func remove_grab(p_grab : Grab) -> void:
|
||||
# Remove the appropriate grab
|
||||
if p_grab == primary:
|
||||
# Remove primary (secondary promoted)
|
||||
print_verbose("%s> %s (primary) released" % [target.name, p_grab.by.name])
|
||||
primary = secondary
|
||||
secondary = null
|
||||
elif p_grab == secondary:
|
||||
# Remove secondary
|
||||
print_verbose("%s> %s (secondary) released" % [target.name, p_grab.by.name])
|
||||
secondary = null
|
||||
|
||||
|
||||
# Discard the driver
|
||||
func discard():
|
||||
remote_path = NodePath()
|
||||
queue_free()
|
||||
|
||||
|
||||
# Create the driver to lerp the target from its current location to the
|
||||
# primary grab-point.
|
||||
static func create_lerp(
|
||||
p_target : Node3D,
|
||||
p_grab : Grab,
|
||||
p_lerp_speed : float) -> XRToolsGrabDriver:
|
||||
|
||||
print_verbose("%s> lerping %s" % [p_target.name, p_grab.by.name])
|
||||
|
||||
# Construct the driver lerping from the current position
|
||||
var driver := XRToolsGrabDriver.new()
|
||||
driver.name = p_target.name + "_driver"
|
||||
driver.top_level = true
|
||||
driver.process_physics_priority = -80
|
||||
driver.state = State.LERP
|
||||
driver.target = p_target
|
||||
driver.primary = p_grab
|
||||
driver.global_transform = p_target.global_transform
|
||||
|
||||
# Calculate the start and duration
|
||||
var end := p_grab.by.global_transform * p_grab.transform
|
||||
var delta := end.origin - p_target.global_position
|
||||
driver.lerp_start = p_target.global_transform
|
||||
driver.lerp_duration = delta.length() / p_lerp_speed
|
||||
|
||||
# Add the driver as a neighbor of the target as RemoteTransform3D nodes
|
||||
# cannot be descendands of the targets they drive.
|
||||
p_target.get_parent().add_child(driver)
|
||||
driver.remote_path = driver.get_path_to(p_target)
|
||||
|
||||
# Return the driver
|
||||
return driver
|
||||
|
||||
|
||||
# Create the driver to instantly snap to the primary grab-point.
|
||||
static func create_snap(
|
||||
p_target : Node3D,
|
||||
p_grab : Grab) -> XRToolsGrabDriver:
|
||||
|
||||
print_verbose("%s> snapping to %s" % [p_target.name, p_grab.by.name])
|
||||
|
||||
# Construct the driver snapped to the held position
|
||||
var driver := XRToolsGrabDriver.new()
|
||||
driver.name = p_target.name + "_driver"
|
||||
driver.top_level = true
|
||||
driver.process_physics_priority = -80
|
||||
driver.state = State.SNAP
|
||||
driver.target = p_target
|
||||
driver.primary = p_grab
|
||||
driver.global_transform = p_grab.by.global_transform * p_grab.transform.inverse()
|
||||
|
||||
# Snapped to grab-point so report arrived
|
||||
p_grab.set_arrived()
|
||||
|
||||
# Add the driver as a neighbor of the target as RemoteTransform3D nodes
|
||||
# cannot be descendands of the targets they drive.
|
||||
p_target.get_parent().add_child(driver)
|
||||
driver.remote_path = driver.get_path_to(p_target)
|
||||
|
||||
# Return the driver
|
||||
return driver
|
||||
|
||||
|
||||
# Calculate the lerp voting from a to b
|
||||
static func _vote(a : float, b : float) -> float:
|
||||
if a == 0.0 and b == 0.0:
|
||||
return 0.0
|
||||
|
||||
return b / (a + b)
|
|
@ -13,6 +13,16 @@ extends Marker3D
|
|||
@export var enabled : bool = true
|
||||
|
||||
|
||||
## Test if a grabber can grab by this grab-point
|
||||
func can_grab(_grabber : Node) -> bool:
|
||||
return enabled
|
||||
## Evaluate fitness of the proposed grab, with 0.0 for not allowed.
|
||||
func can_grab(grabber : Node3D, _current : XRToolsGrabPoint) -> float:
|
||||
if not enabled:
|
||||
return 0.0
|
||||
|
||||
# Return the distance-weighted fitness
|
||||
return _weight(grabber)
|
||||
|
||||
|
||||
# Return a distance-weighted fitness weight in the range (0.0 - max]
|
||||
func _weight(grabber : Node3D, max : float = 1.0) -> float:
|
||||
var distance := global_position.distance_to(grabber.global_position)
|
||||
return max / (1.0 + distance)
|
||||
|
|
|
@ -16,6 +16,13 @@ enum Hand {
|
|||
RIGHT, ## Right hand
|
||||
}
|
||||
|
||||
## Grab mode for this grab point
|
||||
enum Mode {
|
||||
GENERAL, ## General grab point
|
||||
PRIMARY, ## Primary-hand grab point
|
||||
SECONDARY ## Secondary-hand grab point
|
||||
}
|
||||
|
||||
## Hand preview option
|
||||
enum PreviewMode {
|
||||
CLOSED, ## Preview hand closed
|
||||
|
@ -30,15 +37,33 @@ const LEFT_HAND_PATH := "res://addons/godot-xr-tools/hands/scenes/lowpoly/left_h
|
|||
const RIGHT_HAND_PATH := "res://addons/godot-xr-tools/hands/scenes/lowpoly/right_hand_low.tscn"
|
||||
|
||||
|
||||
## Grab-point handle
|
||||
@export var handle : String
|
||||
|
||||
## Which hand this grab point is for
|
||||
@export var hand : Hand: set = _set_hand
|
||||
|
||||
## Hand grab mode
|
||||
@export var mode : Mode = Mode.GENERAL
|
||||
|
||||
## Snap the hand mesh to the grab-point
|
||||
@export var snap_hand : bool = true
|
||||
|
||||
## Hand pose
|
||||
@export var hand_pose : XRToolsHandPoseSettings: set = _set_hand_pose
|
||||
|
||||
## If true, the hand is shown in the editor
|
||||
@export var editor_preview_mode : PreviewMode = PreviewMode.CLOSED: set = _set_editor_preview_mode
|
||||
|
||||
## How much this grab-point drives the position
|
||||
@export var drive_position : float = 1.0
|
||||
|
||||
## How much this grab-point drives the angle
|
||||
@export var drive_angle : float = 1.0
|
||||
|
||||
## How much this grab-point drives the aim
|
||||
@export var drive_aim : float = 0.0
|
||||
|
||||
|
||||
## Hand to use for editor preview
|
||||
var _editor_preview_hand : XRToolsHand
|
||||
|
@ -52,26 +77,27 @@ func _ready():
|
|||
|
||||
|
||||
## Test if a grabber can grab by this grab-point
|
||||
func can_grab(_grabber : Node) -> bool:
|
||||
func can_grab(grabber : Node3D, current : XRToolsGrabPoint) -> float:
|
||||
# Skip if not enabled
|
||||
if not enabled:
|
||||
return false
|
||||
return 0.0
|
||||
|
||||
# Get the grabber controller
|
||||
var controller := _get_grabber_controller(_grabber)
|
||||
if not controller:
|
||||
return false
|
||||
# Verify the hand matches
|
||||
if not _is_correct_hand(grabber):
|
||||
return 0.0
|
||||
|
||||
# Only allow left controller to grab left-hand grab points
|
||||
if hand == Hand.LEFT and controller.tracker != "left_hand":
|
||||
return false
|
||||
# Fail if the hand grab is not permitted
|
||||
if not _is_valid_hand_grab(current):
|
||||
return 0.0
|
||||
|
||||
# Only allow right controller to grab right-hand grab points
|
||||
if hand == Hand.RIGHT and controller.tracker != "right_hand":
|
||||
return false
|
||||
# Get the distance-weighted fitness in the range (0.0 - 0.5], but boost
|
||||
# to [0.5 - 1.0] for valid "specific" grabs.
|
||||
var fitness := _weight(grabber, 0.5)
|
||||
if mode != Mode.GENERAL:
|
||||
fitness += 0.5
|
||||
|
||||
# Allow grab
|
||||
return true
|
||||
# Return the grab fitness
|
||||
return fitness
|
||||
|
||||
|
||||
func _set_hand(new_value : Hand) -> void:
|
||||
|
@ -122,17 +148,58 @@ func _update_editor_preview() -> void:
|
|||
add_child(_editor_preview_hand)
|
||||
|
||||
|
||||
# Is the grabber for the correct hand
|
||||
func _is_correct_hand(grabber : Node3D) -> bool:
|
||||
# Find the controller
|
||||
var controller := _get_grabber_controller(grabber)
|
||||
if not controller:
|
||||
return false
|
||||
|
||||
# If left hand then verify left controller
|
||||
if hand == Hand.LEFT and controller.tracker != "left_hand":
|
||||
return false
|
||||
|
||||
# If right hand then verify right controller
|
||||
if hand == Hand.RIGHT and controller.tracker != "right_hand":
|
||||
return false
|
||||
|
||||
# Controller matches hand
|
||||
return true
|
||||
|
||||
|
||||
# Test if hand grab is permitted
|
||||
func _is_valid_hand_grab(current : XRToolsGrabPoint) -> bool:
|
||||
# Not a valid hand grab if currently held by something other than a hand
|
||||
var current_hand := current as XRToolsGrabPointHand
|
||||
if current and not current_hand:
|
||||
return false
|
||||
|
||||
# Not valid if grabbing the same named handle
|
||||
if handle and current_hand and handle == current_hand.handle:
|
||||
return false
|
||||
|
||||
# Not valid if attempting PRIMARY grab while current is PRIMARY
|
||||
if mode == Mode.PRIMARY and current_hand and current_hand.mode == Mode.PRIMARY:
|
||||
return false
|
||||
|
||||
# Not valid if attempting SECONDARY grab while no current
|
||||
if mode == Mode.SECONDARY and not current_hand:
|
||||
return false
|
||||
|
||||
# Hand is allowed to grab
|
||||
return true
|
||||
|
||||
|
||||
# Get the controller associated with a grabber
|
||||
static func _get_grabber_controller(_grabber : Node) -> XRController3D:
|
||||
static func _get_grabber_controller(grabber : Node3D) -> XRController3D:
|
||||
# Ensure the grabber is valid
|
||||
if not is_instance_valid(_grabber):
|
||||
if not is_instance_valid(grabber):
|
||||
return null
|
||||
|
||||
# Ensure the pickup is a function pickup for a controller
|
||||
var pickup := _grabber as XRToolsFunctionPickup
|
||||
var pickup := grabber as XRToolsFunctionPickup
|
||||
if not pickup:
|
||||
return null
|
||||
|
||||
# Get the controller associated with the pickup
|
||||
return pickup.get_controller()
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
@tool
|
||||
class_name XRToolsGrabPointRedirect
|
||||
extends XRToolsGrabPoint
|
||||
|
||||
|
||||
## Grab point to redirect grabbing to
|
||||
@export var target : XRToolsGrabPoint
|
||||
|
||||
|
||||
## Evaluate fitness of the proposed grab, with 0.0 for not allowed.
|
||||
func can_grab(grabber : Node3D, current : XRToolsGrabPoint) -> float:
|
||||
# Fail if no target
|
||||
if not is_instance_valid(target):
|
||||
return 0.0
|
||||
|
||||
# Consult the target
|
||||
return target.can_grab(grabber, current)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user