]> Untitled Git - william-skin.git/blob - TrackingBone3D.gd
Added NPC
[william-skin.git] / TrackingBone3D.gd
1 @tool
2
3 class_name TrackingBone3D
4 extends SkeletonModifier3D
5
6 enum Axis {
7         X_plus, Y_plus, Z_plus, X_minus, Y_minus, Z_minus
8 }
9
10 @export_enum(" ") var bone: String
11 @export var aim_axis := Axis.Z_plus
12 @export var target: Node3D = null
13
14 var _skeleton: Skeleton3D
15 var _bone_idx: int
16
17
18 func _validate_property(property: Dictionary) -> void:
19         if property.name == "bone":
20                 var skeleton: Skeleton3D = get_skeleton()
21                 if skeleton:
22                         property.hint = PROPERTY_HINT_ENUM
23                         property.hint_string = skeleton.get_concatenated_bone_names()
24
25
26 func _ready() -> void:
27         # for tweening bone poses
28         _skeleton = get_skeleton()
29         if not _skeleton:
30                 push_error("Expected a skeleton!")
31         _bone_idx = _skeleton.find_bone(bone)
32         
33
34 func _process_modification() -> void:
35         if target == null:
36                 return
37
38         var pose: Transform3D = _skeleton.global_transform * _skeleton.get_bone_global_pose(_bone_idx)
39         var looked_at: Transform3D = _w_look_at(pose)
40         
41         _skeleton.set_bone_global_pose(
42                 _bone_idx,
43                 Transform3D(
44                         (_skeleton.global_transform.affine_inverse() * looked_at).basis.orthonormalized(), 
45                         _skeleton.get_bone_global_pose(_bone_idx).origin
46                         )
47                 )
48
49
50 func _w_look_at(from: Transform3D) -> Transform3D:
51         var w: Vector3
52         
53         if aim_axis == Axis.Y_plus:
54                 w = from.basis.x
55         elif aim_axis == Axis.X_plus:
56                 w = from.basis.z
57         elif aim_axis == Axis.Z_plus:
58                 w = from.basis.y
59         elif aim_axis == Axis.Y_minus:
60                 w = w.inverse()
61         elif aim_axis == Axis.X_minus:
62                 w = from.basis.y.inverse()
63         elif aim_axis == Axis.Z_minus:
64                 w = from.basis.y.inverse()
65         
66         var t_v: Vector3 = target.global_position - from.origin
67         var v_y: Vector3 = t_v.normalized()
68         var v_z: Vector3 = w.cross(v_y)
69         v_z = v_z.normalized()
70         var v_x: Vector3 = v_y.cross(v_z)
71         from.basis = Basis(v_x, v_y, v_z)
72         return from