120 lines
3.8 KiB
GDScript
120 lines
3.8 KiB
GDScript
# 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)
|