# XRToolsHandPoseController.gd # Hängt am XRController3D (Left/Right) # Verwaltet Hand-Posen basierend auf Trigger und Grip extends XRController3D class_name XRToolsHandPoseController @export var hand_modifier: XRHandModifier3D @export var hand_side: String = "left" # "left" oder "right" var current_pose: String = "open" var trigger_value: float = 0.0 var grip_value: float = 0.0 var pose_blend: float = 0.0 var target_pose_blend: float = 0.0 func _ready() -> void: if not hand_modifier: push_error("XRToolsHandPoseController: XRHandModifier3D nicht zugewiesen!") return print("Hand-Posen initialisiert für: ", hand_side) func _process(delta: float) -> void: _update_input() _update_hand_animation(delta) func _update_input() -> void: # Trigger und Grip direkt vom Controller auslesen trigger_value = get_float("trigger") grip_value = get_float("grip") # Pose basierend auf Input bestimmen if grip_value > 0.7: target_pose_blend = 0.0 current_pose = "fist" elif trigger_value > 0.5 and grip_value < 0.3: target_pose_blend = 1.0 current_pose = "pointing" else: target_pose_blend = 2.0 current_pose = "open" func _update_hand_animation(delta: float) -> void: # Sanftes Blending zwischen Posen pose_blend = lerp(pose_blend, target_pose_blend, 5.0 * delta) # XRHandModifier3D animiert automatisch basierend auf Skeleton-Posen # Wende Bone-Transformationen direkt an var skeleton: Skeleton3D = hand_modifier.get_parent() as Skeleton3D if not skeleton: return # Passe Finger-Bones basierend auf aktuelle Pose an _apply_pose_to_skeleton(skeleton, current_pose, pose_blend) func _apply_pose_to_skeleton(skeleton: Skeleton3D, pose: String, blend: float) -> void: """Wende die Pose auf die Skeleton-Bones an""" # Finde alle Finger-Bones var thumb = _find_bone_index(skeleton, "Thumb") var index = _find_bone_index(skeleton, "Index") var middle = _find_bone_index(skeleton, "Middle") var ring = _find_bone_index(skeleton, "Ring") var pinky = _find_bone_index(skeleton, "Pinky") match pose: "fist": # Alle Finger gekrümmt _bend_finger(skeleton, thumb, blend) _bend_finger(skeleton, index, blend) _bend_finger(skeleton, middle, blend) _bend_finger(skeleton, ring, blend) _bend_finger(skeleton, pinky, blend) "pointing": # Zeigefinger gestreckt, andere gekrümmt _extend_finger(skeleton, index, blend) _bend_finger(skeleton, thumb, blend * 0.5) _bend_finger(skeleton, middle, blend) _bend_finger(skeleton, ring, blend) _bend_finger(skeleton, pinky, blend) "open": # Alle Finger gestreckt _extend_finger(skeleton, thumb, blend) _extend_finger(skeleton, index, blend) _extend_finger(skeleton, middle, blend) _extend_finger(skeleton, ring, blend) _extend_finger(skeleton, pinky, blend) func _find_bone_index(skeleton: Skeleton3D, bone_name: String) -> int: """Finde den Index eines Bones nach Name (Substring-Match)""" for i in range(skeleton.get_bone_count()): if skeleton.get_bone_name(i).to_lower().contains(bone_name.to_lower()): return i return -1 func _bend_finger(skeleton: Skeleton3D, bone_idx: int, amount: float) -> void: """Krümme einen Finger (Rotation um X-Achse)""" if bone_idx < 0: return var current_pose = skeleton.get_bone_pose(bone_idx) var bent_rotation = Quaternion.from_euler(Vector3(amount * 1.5, 0, 0)) current_pose.basis = Basis(bent_rotation) skeleton.set_bone_pose(bone_idx, current_pose) func _extend_finger(skeleton: Skeleton3D, bone_idx: int, amount: float) -> void: """Strecke einen Finger (Rotation zurück auf Neutral)""" if bone_idx < 0: return var current_pose = skeleton.get_bone_pose(bone_idx) var extended_rotation = Quaternion.from_euler(Vector3(-amount * 0.5, 0, 0)) current_pose.basis = Basis(extended_rotation) skeleton.set_bone_pose(bone_idx, current_pose)