class_name WilliamSkin extends Node3D @onready var animation_tree: AnimationTree = $AnimationTree @onready var skeleton: Skeleton3D = $base/rig/Skeleton3D # get tracking bones from skeleton var _eye_left_index := -1 var _eye_right_index := -1 var _eye_track_target: Vector3 = Vector3.ZERO var _head_index := -1 var _head_track_target: Vector3 = Vector3.ZERO func _ready() -> void: _eye_left_index = skeleton.find_bone("DEF-eye.L") _eye_right_index = skeleton.find_bone("DEF-eye.R") _head_index = skeleton.find_bone("DEF-spine.006") func _process(_delta: float) -> void: if _eye_track_target != Vector3.ZERO: _process_eyes_tracking() if _head_track_target != Vector3.ZERO: _process_head_tracking() # manage eye tracking func set_eyes_target(target: Vector3) -> void: _eye_track_target = target func _process_eyes_tracking() -> void: # TODO: this is broken! for i in [_eye_left_index, _eye_right_index]: var bone_pose: Transform3D = skeleton.global_transform * skeleton.get_bone_global_pose(i) bone_pose = bone_pose.looking_at(_eye_track_target) var axis: Vector3 = bone_pose.basis.x bone_pose = bone_pose.rotated_local(axis, -PI/2) #skeleton.set_bone_global_pose_override(i, skeleton.global_transform.affine_inverse() * bone_pose, 1, true) # ^^^ this sets the bone position relative to its rest position, not after animation! # TODO: manage head tracking func set_head_target(target: Vector3) -> void: _head_track_target = target func _process_head_tracking() -> void: pass # manage talking and expressions func talk() -> void: animation_tree.set("parameters/motion/transition_request", "talk") # manage vectored movement func current_state() -> String: return animation_tree.get("parameters/motion/current_state") func set_hips_direction(direction: float) -> void: animation_tree.set("parameters/hips_direction/blend_position", clamp(direction, -PI / 2, PI / 2)) func get_hips_direction() -> float: return animation_tree.get("parameters/hips_direction/blend_position") func pose() -> void: animation_tree.set("parameters/motion/transition_request", "pose") func idle() -> void: animation_tree.set("parameters/motion/transition_request", "idle") func move_forward() -> void: animation_tree.set("parameters/motion/transition_request", "forward") func move_backward() -> void: animation_tree.set("parameters/motion/transition_request", "backward") func movement_speed(speed: float) -> void: animation_tree.set("parameters/forward/blend_position", speed) animation_tree.set("parameters/backward/blend_position", speed) func jump() -> void: animation_tree.set("parameters/motion/transition_request", "fall") func fall() -> void: animation_tree.set("parameters/motion/transition_request", "fall") func landing() -> void: animation_tree.set("parameters/motion/transition_request", "landing")