3 class_name TrackingBone3D
4 extends SkeletonModifier3D
10 @export_enum(" ") var bone: String
11 @export var aim_axis := Axis.Z_plus
12 @export var pivot_axis := Axis.Y_plus
13 @export var target: Vector3 = Vector3(0, 0, 0)
16 func _validate_property(property: Dictionary) -> void:
17 if property.name == "bone":
18 var skeleton: Skeleton3D = get_skeleton()
20 property.hint = PROPERTY_HINT_ENUM
21 property.hint_string = skeleton.get_concatenated_bone_names()
24 func _process_modification() -> void:
25 var skeleton: Skeleton3D = get_skeleton()
27 return # Never happen, but for the safety.
28 var bone_idx: int = skeleton.find_bone(bone)
29 var _parent_idx: int = skeleton.get_bone_parent(bone_idx)
30 var pose: Transform3D = skeleton.global_transform * skeleton.get_bone_global_pose(bone_idx)
32 var looked_at: Transform3D = _w_look_at(pose)
33 #var looked_at: Transform3D = pose.looking_at(target, Vector3.UP)
34 #var axis: Vector3 = looked_at.basis.y
35 #looked_at = looked_at.rotated(axis, PI)
37 skeleton.set_bone_global_pose(
40 (skeleton.global_transform.affine_inverse() * looked_at).basis.orthonormalized(),
41 skeleton.get_bone_global_pose(bone_idx).origin
46 func _w_look_at(from: Transform3D) -> Transform3D:
48 var w: Vector3 = from.basis.x
50 if aim_axis == Axis.X_plus:
52 elif aim_axis == Axis.Z_plus:
55 var t_v: Vector3 = target - from.origin
56 var v_y: Vector3 = t_v.normalized()
57 var v_z: Vector3 = w.cross(v_y)
58 v_z = v_z.normalized()
59 var v_x: Vector3 = v_y.cross(v_z)
60 from.basis = Basis(v_x, v_y, v_z)