diff --git a/addons/godot-xr-tools/functions/function_pickup.gd b/addons/godot-xr-tools/functions/function_pickup.gd index db4d1d13..49af7f95 100644 --- a/addons/godot-xr-tools/functions/function_pickup.gd +++ b/addons/godot-xr-tools/functions/function_pickup.gd @@ -388,6 +388,11 @@ func drop_object() -> void: _velocity_averager.linear_velocity() * impulse_factor, _velocity_averager.angular_velocity()) picked_up_object = null + + if _collision_hand: + # Reset the held weight + _collision_hand.set_held_weight(0.0) + emit_signal("has_dropped") diff --git a/addons/godot-xr-tools/hands/collision_hand.gd b/addons/godot-xr-tools/hands/collision_hand.gd index 92cd1532..ac758449 100644 --- a/addons/godot-xr-tools/hands/collision_hand.gd +++ b/addons/godot-xr-tools/hands/collision_hand.gd @@ -39,6 +39,8 @@ const ORIENT_DISPLACEMENT := 0.05 # Distance to teleport hands const TELEPORT_DISTANCE := 1.0 +# We reached our teleport distance +signal max_distance_reached ## Controls the hand collision mode @export var mode : CollisionHandMode = CollisionHandMode.COLLIDE @@ -68,6 +70,15 @@ const TELEPORT_DISTANCE := 1.0 notify_property_list_changed() + +## Minimum force we can exert on a picked up object +@export_range(1.0, 1000.0, 0.1, "suffix:N") var min_pickup_force : float = 15.0 + +## Force we exert on a picked up object when hand is at maximum distance +## before letting go. +@export_range(1.0, 1000.0, 0.1, "suffix:N") var max_pickup_force : float = 400.0 + + # Controller to target (if no target overrides) var _controller : XRController3D @@ -81,6 +92,11 @@ var _target : Node3D var _palm_collision_shape : CollisionShape3D var _digit_collision_shapes : Dictionary +# The weight held by this hand +var _held_weight : float = 0.0 + +# Movement on last frame +var _last_movement : Vector3 = Vector3() ## Target-override class class TargetOverride: @@ -96,6 +112,11 @@ class TargetOverride: priority = p +# Update the weight attributed to this hand (updated from pickable system). +func set_held_weight(new_weight): + _held_weight = new_weight + + # Add support for is_xr_class on XRTools classes func is_xr_class(name : String) -> bool: return name == "XRToolsCollisionHand" @@ -156,14 +177,17 @@ func _ready(): # Handle physics processing -func _physics_process(_delta): +func _physics_process(delta): # Do not process if in the editor if Engine.is_editor_hint(): return + var current_position = global_position + # Move to the current target - _move_to_target() + _move_to_target(delta) + _last_movement = global_position - current_position ## This function adds a target override. The collision hand will attempt to ## move to the highest priority target, or the [XRController3D] if no override @@ -227,7 +251,7 @@ static func find_right(node : Node) -> XRToolsCollisionHand: # This function moves the collision hand to the target node. -func _move_to_target(): +func _move_to_target(delta): # Handle DISABLED or no target if mode == CollisionHandMode.DISABLED or not _target: return @@ -239,12 +263,48 @@ func _move_to_target(): # Handle too far from target if global_position.distance_to(_target.global_position) > TELEPORT_DISTANCE: + max_distance_reached.emit() + global_transform = _target.global_transform return - # Orient the hand then move + # Orient the hand global_transform.basis = _target.global_transform.basis - move_and_slide(_target.global_position - global_position) + + # Adjust target position if we're holding something + var target_movement : Vector3 = _target.global_position - global_position + if _held_weight > 0.0: + var gravity_state := PhysicsServer3D.body_get_direct_state(get_rid()) + var gravity = gravity_state.total_gravity * delta + + # Calculate the movement of our held object if we weren't holding it + var base_movement : Vector3 = _last_movement * 0.2 + gravity + + # How much movement is left until we reach our target + var remaining_movement = target_movement - base_movement + + # The below is an approximation as we're not taking the logarithmic + # nature of force acceleration into account for simplicitiy. + + # Distance over time gives our needed acceleration which + # gives us the force needed on the object to move it to our + # target destination. + # But dividing and then multiplying over delta and mass is wasteful. + var needed_distance = remaining_movement.length() + + # Force we can exert on the object + var force = min_pickup_force + \ + (target_movement.length() * (max_pickup_force-min_pickup_force) / TELEPORT_DISTANCE) + + # How much can we move our object? + var possible_distance = delta * force / _held_weight + if possible_distance < needed_distance: + # We can't make our distance? adjust our movement! + remaining_movement *= (possible_distance / needed_distance) + target_movement = base_movement + remaining_movement + + # And move + move_and_slide(target_movement) force_update_transform() diff --git a/addons/godot-xr-tools/objects/grab_points/grab.gd b/addons/godot-xr-tools/objects/grab_points/grab.gd index d749b35a..4b9aaffa 100644 --- a/addons/godot-xr-tools/objects/grab_points/grab.gd +++ b/addons/godot-xr-tools/objects/grab_points/grab.gd @@ -78,6 +78,7 @@ func _init( # Apply collision exceptions if collision_hand: + collision_hand.max_distance_reached.connect(_on_max_distance_reached) _add_collision_exceptions(what) @@ -154,6 +155,11 @@ func release() -> void: what.released.emit(what, by) +# Hand has moved too far away from object, can no longer hold on to it. +func _on_max_distance_reached() -> void: + pickup.drop_object() + + # Set hand-pose overrides func _set_hand_pose() -> void: # Skip if not hand @@ -192,7 +198,6 @@ func _add_collision_exceptions(from : Node): # If this is a physics body, add an exception if from is PhysicsBody3D: - print_debug("Add collision exception for ", from.name) # Make sure we don't collide with what we're holding _collision_exceptions.push_back(from) collision_hand.add_collision_exception_with(from) diff --git a/addons/godot-xr-tools/objects/grab_points/grab_driver.gd b/addons/godot-xr-tools/objects/grab_points/grab_driver.gd index 3221ffbf..48ef30f9 100644 --- a/addons/godot-xr-tools/objects/grab_points/grab_driver.gd +++ b/addons/godot-xr-tools/objects/grab_points/grab_driver.gd @@ -89,6 +89,7 @@ func _physics_process(delta : float) -> void: else: # Lerp completed state = GrabState.SNAP + _update_weight() if primary: primary.set_arrived() if secondary: secondary.set_arrived() @@ -112,6 +113,7 @@ func add_grab(p_grab : Grab) -> void: # If snapped then report arrived at the new grab if state == GrabState.SNAP: + _update_weight() p_grab.set_arrived() @@ -138,6 +140,9 @@ func remove_grab(p_grab : Grab) -> void: print_verbose("%s> %s (secondary) released" % [target.name, p_grab.by.name]) secondary = null + if state == GrabState.SNAP: + _update_weight() + # Discard the driver func discard(): @@ -204,6 +209,8 @@ static func create_snap( p_target.get_parent().add_child(driver) driver.remote_path = driver.get_path_to(p_target) + driver._update_weight() + # Return the driver return driver @@ -214,3 +221,17 @@ static func _vote(a : float, b : float) -> float: return 0.0 return b / (a + b) + + +# Update the weight on collision hands +func _update_weight(): + if primary: + var weight : float = target.mass + if secondary: + # Each hand carries half the weight + weight = weight / 2.0 + if secondary.collision_hand: + secondary.collision_hand.set_held_weight(weight) + + if primary.collision_hand: + primary.collision_hand.set_held_weight(weight) diff --git a/assets/3dmodelscc0/models/scenes/sniper_rifle.tscn b/assets/3dmodelscc0/models/scenes/sniper_rifle.tscn index 7c743fb9..2d914afc 100644 --- a/assets/3dmodelscc0/models/scenes/sniper_rifle.tscn +++ b/assets/3dmodelscc0/models/scenes/sniper_rifle.tscn @@ -112,6 +112,7 @@ radius = 0.001 [node name="SniperRifle" instance=ExtResource("1_lpv7q")] collision_mask = 7 +mass = 4.0 script = ExtResource("2_bdnea") second_hand_grab = 2 diff --git a/assets/meshes/picatinny_rail/picatinny_30.glb.import b/assets/meshes/picatinny_rail/picatinny_30.glb.import index c7960e35..e96341c3 100644 --- a/assets/meshes/picatinny_rail/picatinny_30.glb.import +++ b/assets/meshes/picatinny_rail/picatinny_30.glb.import @@ -17,7 +17,6 @@ nodes/root_type="Node3D" nodes/root_name="Scene Root" nodes/apply_root_scale=true nodes/root_scale=1.0 -nodes/import_as_skeleton_bones=false meshes/ensure_tangents=true meshes/generate_lods=true meshes/create_shadow_meshes=true @@ -29,7 +28,6 @@ animation/import=false animation/fps=30 animation/trimming=false animation/remove_immutable_tracks=true -animation/import_rest_as_RESET=false import_script/path="" _subresources={} gltf/naming_version=0 diff --git a/scenes/pickable_demo/objects/grab_ball.tscn b/scenes/pickable_demo/objects/grab_ball.tscn index f1c6393d..244caef5 100644 --- a/scenes/pickable_demo/objects/grab_ball.tscn +++ b/scenes/pickable_demo/objects/grab_ball.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=10 format=3 uid="uid://clta811tt773x"] +[gd_scene load_steps=11 format=3 uid="uid://clta811tt773x"] [ext_resource type="PackedScene" uid="uid://c8l60rnugru40" path="res://addons/godot-xr-tools/objects/pickable.tscn" id="1"] [ext_resource type="Material" path="res://assets/wahooney.itch.io/brown_grid_triplanar.tres" id="2"] @@ -6,6 +6,9 @@ [ext_resource type="Script" path="res://addons/godot-xr-tools/objects/highlight/highlight_visible.gd" id="3"] [ext_resource type="PackedScene" uid="uid://ctw7nbntd5pcj" path="res://addons/godot-xr-tools/objects/grab_points/grab_point_hand_right.tscn" id="3_0q4lf"] +[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_bv5s3"] +bounce = 0.8 + [sub_resource type="SphereShape3D" id="2"] margin = 0.01 radius = 0.2 @@ -29,6 +32,7 @@ albedo_color = Color(1, 1, 0, 1) [node name="GrabBall" instance=ExtResource("1")] collision_mask = 720903 +physics_material_override = SubResource("PhysicsMaterial_bv5s3") ranged_grab_method = 2 second_hand_grab = 2 diff --git a/scenes/pickable_demo/objects/hammer.tscn b/scenes/pickable_demo/objects/hammer.tscn index 0c28b5ca..dcc0f1f0 100644 --- a/scenes/pickable_demo/objects/hammer.tscn +++ b/scenes/pickable_demo/objects/hammer.tscn @@ -28,6 +28,7 @@ size = Vector3(0.1, 0.1, 0.2) [node name="Hammer" instance=ExtResource("1")] collision_mask = 7 +mass = 2.0 ranged_grab_method = 0 second_hand_grab = 2 diff --git a/scenes/pickable_demo/objects/picatinny_scope.tscn b/scenes/pickable_demo/objects/picatinny_scope.tscn index 68b9232c..c89d8d31 100644 --- a/scenes/pickable_demo/objects/picatinny_scope.tscn +++ b/scenes/pickable_demo/objects/picatinny_scope.tscn @@ -45,6 +45,7 @@ blend_shape_mode = 0 shadow_mesh = SubResource("ArrayMesh_mmp6s") [node name="PicatinnyScope" groups=["Picatinny"] instance=ExtResource("1_1xi8m")] +mass = 0.5 [node name="CollisionShape3D" parent="." index="0"] transform = Transform3D(-1, 0, 8.74228e-08, 0, 1, 0, -8.74228e-08, 0, -1, 0.0028, 0.0208471, -0.0617341) diff --git a/scenes/pickable_demo/objects/teacup.tscn b/scenes/pickable_demo/objects/teacup.tscn index ce521ec4..38d5eea8 100644 --- a/scenes/pickable_demo/objects/teacup.tscn +++ b/scenes/pickable_demo/objects/teacup.tscn @@ -57,6 +57,7 @@ open_pose = ExtResource("7_m23hc") closed_pose = ExtResource("7_m23hc") [node name="Teacup" groups=["Teacup"] instance=ExtResource("1_q232w")] +mass = 0.2 second_hand_grab = 1 [node name="Teacup" type="MeshInstance3D" parent="." index="0"] diff --git a/scenes/pickable_demo/pickable_demo.tscn b/scenes/pickable_demo/pickable_demo.tscn index 0482b559..f2c96459 100644 --- a/scenes/pickable_demo/pickable_demo.tscn +++ b/scenes/pickable_demo/pickable_demo.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=45 format=3 uid="uid://0c76wodjd7rm"] +[gd_scene load_steps=46 format=3 uid="uid://0c76wodjd7rm"] [ext_resource type="PackedScene" uid="uid://qbmx03iibuuu" path="res://addons/godot-xr-tools/staging/scene_base.tscn" id="1"] [ext_resource type="Script" path="res://scenes/demo_scene_base.gd" id="2_kjksy"] @@ -32,67 +32,67 @@ [ext_resource type="PackedScene" uid="uid://bxk2dud5pq1uf" path="res://scenes/pickable_demo/objects/knife.tscn" id="19_6grml"] [ext_resource type="Script" path="res://addons/godot-xr-tools/objects/return_to_snap_zone.gd" id="19_iqmkd"] [ext_resource type="PackedScene" uid="uid://bmjemjgtnpkpo" path="res://assets/3dmodelscc0/models/scenes/sniper_rifle.tscn" id="25_xgu4l"] -[ext_resource type="PackedScene" uid="uid://dfu08adatg63i" path="res://scenes/pickable_demo/objects/picatinny_scope.tscn" id="26_x40vw"] +[ext_resource type="PackedScene" uid="uid://deuxld12hxsq0" path="res://scenes/pickable_demo/objects/picatinny_scope.tscn" id="26_x40vw"] -[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_lk0rx"] +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_lmsx6"] animation = &"Grip" -[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_byatp"] +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_bwyq3"] animation = &"Grip" -[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_lh7tw"] +[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_o7t7c"] 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_0hde5"] +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_jfy5w"] animation = &"Grip 5" -[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_1myux"] +[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_4tpt7"] 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_add5h"] +[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_p6s08"] graph_offset = Vector2(-536, 11) -nodes/ClosedHand1/node = SubResource("AnimationNodeAnimation_lk0rx") +nodes/ClosedHand1/node = SubResource("AnimationNodeAnimation_lmsx6") nodes/ClosedHand1/position = Vector2(-600, 300) -nodes/ClosedHand2/node = SubResource("AnimationNodeAnimation_byatp") +nodes/ClosedHand2/node = SubResource("AnimationNodeAnimation_bwyq3") nodes/ClosedHand2/position = Vector2(-360, 300) -nodes/Grip/node = SubResource("AnimationNodeBlend2_lh7tw") +nodes/Grip/node = SubResource("AnimationNodeBlend2_o7t7c") nodes/Grip/position = Vector2(0, 20) -nodes/OpenHand/node = SubResource("AnimationNodeAnimation_0hde5") +nodes/OpenHand/node = SubResource("AnimationNodeAnimation_jfy5w") nodes/OpenHand/position = Vector2(-600, 100) -nodes/Trigger/node = SubResource("AnimationNodeBlend2_1myux") +nodes/Trigger/node = SubResource("AnimationNodeBlend2_4tpt7") nodes/Trigger/position = Vector2(-360, 20) node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"] -[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_0loxr"] +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_wbiva"] animation = &"Grip" -[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_brc6o"] +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_efvb2"] animation = &"Grip" -[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_kiqrg"] +[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_v66ik"] filter_enabled = true filters = ["Armature/Skeleton3D:Little_Distal_R", "Armature/Skeleton3D:Little_Intermediate_R", "Armature/Skeleton3D:Little_Metacarpal_R", "Armature/Skeleton3D:Little_Proximal_R", "Armature/Skeleton3D:Middle_Distal_R", "Armature/Skeleton3D:Middle_Intermediate_R", "Armature/Skeleton3D:Middle_Metacarpal_R", "Armature/Skeleton3D:Middle_Proximal_R", "Armature/Skeleton3D:Ring_Distal_R", "Armature/Skeleton3D:Ring_Intermediate_R", "Armature/Skeleton3D:Ring_Metacarpal_R", "Armature/Skeleton3D:Ring_Proximal_R", "Armature/Skeleton3D:Thumb_Distal_R", "Armature/Skeleton3D:Thumb_Metacarpal_R", "Armature/Skeleton3D:Thumb_Proximal_R", "Armature/Skeleton:Little_Distal_R", "Armature/Skeleton:Little_Intermediate_R", "Armature/Skeleton:Little_Proximal_R", "Armature/Skeleton:Middle_Distal_R", "Armature/Skeleton:Middle_Intermediate_R", "Armature/Skeleton:Middle_Proximal_R", "Armature/Skeleton:Ring_Distal_R", "Armature/Skeleton:Ring_Intermediate_R", "Armature/Skeleton:Ring_Proximal_R", "Armature/Skeleton:Thumb_Distal_R", "Armature/Skeleton:Thumb_Proximal_R"] -[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_a6vop"] +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_qt4i3"] animation = &"Grip 5" -[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_utpbw"] +[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_3osea"] filter_enabled = true filters = ["Armature/Skeleton3D:Index_Distal_R", "Armature/Skeleton3D:Index_Intermediate_R", "Armature/Skeleton3D:Index_Metacarpal_R", "Armature/Skeleton3D:Index_Proximal_R", "Armature/Skeleton:Index_Distal_R", "Armature/Skeleton:Index_Intermediate_R", "Armature/Skeleton:Index_Proximal_R"] -[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_utbhi"] +[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_6sler"] graph_offset = Vector2(-552.664, 107.301) -nodes/ClosedHand1/node = SubResource("AnimationNodeAnimation_0loxr") +nodes/ClosedHand1/node = SubResource("AnimationNodeAnimation_wbiva") nodes/ClosedHand1/position = Vector2(-600, 300) -nodes/ClosedHand2/node = SubResource("AnimationNodeAnimation_brc6o") +nodes/ClosedHand2/node = SubResource("AnimationNodeAnimation_efvb2") nodes/ClosedHand2/position = Vector2(-360, 300) -nodes/Grip/node = SubResource("AnimationNodeBlend2_kiqrg") +nodes/Grip/node = SubResource("AnimationNodeBlend2_v66ik") nodes/Grip/position = Vector2(0, 40) -nodes/OpenHand/node = SubResource("AnimationNodeAnimation_a6vop") +nodes/OpenHand/node = SubResource("AnimationNodeAnimation_qt4i3") nodes/OpenHand/position = Vector2(-600, 100) -nodes/Trigger/node = SubResource("AnimationNodeBlend2_utpbw") +nodes/Trigger/node = SubResource("AnimationNodeBlend2_3osea") nodes/Trigger/position = Vector2(-360, 40) node_connections = [&"Grip", 0, &"Trigger", &"Grip", 1, &"ClosedHand2", &"Trigger", 0, &"OpenHand", &"Trigger", 1, &"ClosedHand1", &"output", 0, &"Grip"] @@ -101,11 +101,33 @@ script = ExtResource("2_kjksy") [node name="XRToolsCollisionHand" parent="XROrigin3D/LeftHand" index="0" node_paths=PackedStringArray("hand_skeleton") instance=ExtResource("3_m7tr4")] hand_skeleton = NodePath("LeftHand/Hand_Nails_low_L/Armature/Skeleton3D") +min_pickup_force = 15.0 [node name="LeftHand" parent="XROrigin3D/LeftHand/XRToolsCollisionHand" index="0" instance=ExtResource("7_ywaf6")] +[node name="Skeleton3D" parent="XROrigin3D/LeftHand/XRToolsCollisionHand/LeftHand/Hand_Nails_low_L/Armature" index="0"] +bones/1/rotation = Quaternion(0.323537, -2.56577e-05, -0.0272204, 0.945824) +bones/2/rotation = Quaternion(-0.0904441, -0.0415175, -0.166293, 0.981042) +bones/3/rotation = Quaternion(-0.0466199, 0.020971, 0.0103276, 0.998639) +bones/5/rotation = Quaternion(-0.00128455, -0.0116081, -0.0168259, 0.99979) +bones/6/rotation = Quaternion(0.102925, -0.00993208, -0.00794417, 0.994608) +bones/7/rotation = Quaternion(-0.012859, -0.0236108, -0.323258, 0.945929) +bones/8/rotation = Quaternion(0.0120575, -0.00929194, -0.247472, 0.968775) +bones/10/rotation = Quaternion(-0.0357539, -0.000400032, 0.00636764, 0.99934) +bones/11/rotation = Quaternion(-0.00264964, -0.00114471, -0.125992, 0.992027) +bones/12/rotation = Quaternion(0.0394225, 0.00193393, -0.228074, 0.972843) +bones/13/rotation = Quaternion(-0.0123395, -0.00881294, -0.280669, 0.959685) +bones/15/rotation = Quaternion(-0.0702656, 0.0101908, -0.0243307, 0.99718) +bones/16/rotation = Quaternion(-0.0320634, -0.00223624, -0.0686366, 0.997124) +bones/17/rotation = Quaternion(0.0253452, 0.00812462, -0.249005, 0.968136) +bones/18/rotation = Quaternion(0.00252232, 0.00788073, -0.243204, 0.96994) +bones/20/rotation = Quaternion(-0.0917369, 0.0203027, -0.010183, 0.995524) +bones/21/rotation = Quaternion(-0.0625182, -0.00022572, -0.115393, 0.991351) +bones/22/rotation = Quaternion(0.0585786, 0.0216483, -0.269905, 0.96086) +bones/23/rotation = Quaternion(0.00687177, -0.00357275, -0.211953, 0.977249) + [node name="BoneAttachment3D" type="BoneAttachment3D" parent="XROrigin3D/LeftHand/XRToolsCollisionHand/LeftHand/Hand_Nails_low_L/Armature/Skeleton3D" index="1"] -transform = Transform3D(0.54083, 0.840812, -0.0231736, -0.0826267, 0.0805244, 0.993322, 0.837063, -0.535304, 0.113024, 0.0399019, 0.0402829, -0.150096) +transform = Transform3D(0.54083, 0.840813, -0.0231736, -0.0826267, 0.0805243, 0.993322, 0.837064, -0.535303, 0.113023, 0.039902, 0.0402828, -0.150096) bone_name = "Index_Tip_L" bone_idx = 9 @@ -116,7 +138,7 @@ push_bodies = false [node name="AnimationTree" parent="XROrigin3D/LeftHand/XRToolsCollisionHand/LeftHand" index="1"] root_node = NodePath("../Hand_Nails_low_L") -tree_root = SubResource("AnimationNodeBlendTree_add5h") +tree_root = SubResource("AnimationNodeBlendTree_p6s08") [node name="MovementDirect" parent="XROrigin3D/LeftHand/XRToolsCollisionHand" index="1" instance=ExtResource("7")] strafe = true @@ -129,11 +151,33 @@ ranged_angle = 10.0 [node name="XRToolsCollisionHand" parent="XROrigin3D/RightHand" index="0" node_paths=PackedStringArray("hand_skeleton") instance=ExtResource("3_m7tr4")] hand_skeleton = NodePath("RightHand/Hand_Nails_R/Armature/Skeleton3D") +min_pickup_force = 15.0 [node name="RightHand" parent="XROrigin3D/RightHand/XRToolsCollisionHand" index="0" instance=ExtResource("9_v8epv")] +[node name="Skeleton3D" parent="XROrigin3D/RightHand/XRToolsCollisionHand/RightHand/Hand_Nails_R/Armature" index="0"] +bones/1/rotation = Quaternion(0.323537, 2.56577e-05, 0.0272204, 0.945824) +bones/2/rotation = Quaternion(-0.0904441, 0.0415175, 0.166293, 0.981042) +bones/3/rotation = Quaternion(-0.0466199, -0.020971, -0.0103276, 0.998639) +bones/5/rotation = Quaternion(-0.00128455, 0.0116081, 0.0168259, 0.99979) +bones/6/rotation = Quaternion(0.102925, 0.00993208, 0.00794419, 0.994608) +bones/7/rotation = Quaternion(-0.012859, 0.0236108, 0.323258, 0.945929) +bones/8/rotation = Quaternion(0.0120575, 0.00929193, 0.247472, 0.968775) +bones/10/rotation = Quaternion(-0.0357539, 0.000400032, -0.00636763, 0.99934) +bones/11/rotation = Quaternion(-0.00264964, 0.00114471, 0.125992, 0.992027) +bones/12/rotation = Quaternion(0.0394225, -0.00193393, 0.228074, 0.972843) +bones/13/rotation = Quaternion(-0.0123395, 0.00881294, 0.280669, 0.959685) +bones/15/rotation = Quaternion(-0.0702656, -0.0101908, 0.0243307, 0.99718) +bones/16/rotation = Quaternion(-0.0320634, 0.00223624, 0.0686366, 0.997124) +bones/17/rotation = Quaternion(0.0253452, -0.00812462, 0.249005, 0.968136) +bones/18/rotation = Quaternion(0.00252233, -0.00788073, 0.243204, 0.96994) +bones/20/rotation = Quaternion(-0.0917369, -0.0203027, 0.010183, 0.995524) +bones/21/rotation = Quaternion(-0.0625182, 0.000225721, 0.115393, 0.991351) +bones/22/rotation = Quaternion(0.0585786, -0.0216483, 0.269905, 0.96086) +bones/23/rotation = Quaternion(0.00687177, 0.00357275, 0.211953, 0.977249) + [node name="BoneAttachment3D" type="BoneAttachment3D" parent="XROrigin3D/RightHand/XRToolsCollisionHand/RightHand/Hand_Nails_R/Armature/Skeleton3D" index="1"] -transform = Transform3D(0.54083, -0.840812, 0.0231736, 0.0826267, 0.0805244, 0.993322, -0.837063, -0.535304, 0.113024, -0.0399019, 0.0402829, -0.150096) +transform = Transform3D(0.540829, -0.840813, 0.0231736, 0.0826268, 0.0805242, 0.993322, -0.837064, -0.535303, 0.113024, -0.039902, 0.0402828, -0.150096) bone_name = "Index_Tip_R" bone_idx = 9 @@ -144,7 +188,7 @@ push_bodies = false [node name="AnimationTree" parent="XROrigin3D/RightHand/XRToolsCollisionHand/RightHand" index="1"] root_node = NodePath("../Hand_Nails_R") -tree_root = SubResource("AnimationNodeBlendTree_utbhi") +tree_root = SubResource("AnimationNodeBlendTree_6sler") [node name="MovementDirect" parent="XROrigin3D/RightHand/XRToolsCollisionHand" index="1" instance=ExtResource("7")]