extends SkeletonModifier3D
enum Axis {
- X_plus, Y_plus, Z_plus
+ X_plus, Y_plus, Z_plus, X_minus, Y_minus, Z_minus
}
@export_enum(" ") var bone: String
@export var aim_axis := Axis.Z_plus
-@export var pivot_axis := Axis.Y_plus
-@export var target: Vector3 = Vector3(0, 0, 0)
+@export var target: Node3D = null
+
+var _skeleton: Skeleton3D
+var _bone_idx: int
func _validate_property(property: Dictionary) -> void:
property.hint_string = skeleton.get_concatenated_bone_names()
-func _process_modification() -> void:
- var skeleton: Skeleton3D = get_skeleton()
- if !skeleton:
- return # Never happen, but for the safety.
- var bone_idx: int = skeleton.find_bone(bone)
- var _parent_idx: int = skeleton.get_bone_parent(bone_idx)
- var pose: Transform3D = skeleton.global_transform * skeleton.get_bone_global_pose(bone_idx)
+func _ready() -> void:
+ # for tweening bone poses
+ _skeleton = get_skeleton()
+ if not _skeleton:
+ push_error("Expected a skeleton!")
+ _bone_idx = _skeleton.find_bone(bone)
+
+func _process_modification() -> void:
+ if target == null:
+ return
+
+ var pose: Transform3D = _skeleton.global_transform * _skeleton.get_bone_global_pose(_bone_idx)
var looked_at: Transform3D = _w_look_at(pose)
- #var looked_at: Transform3D = pose.looking_at(target, Vector3.UP)
- #var axis: Vector3 = looked_at.basis.y
- #looked_at = looked_at.rotated(axis, PI)
- skeleton.set_bone_global_pose(
- bone_idx,
+ _skeleton.set_bone_global_pose(
+ _bone_idx,
Transform3D(
- (skeleton.global_transform.affine_inverse() * looked_at).basis.orthonormalized(),
- skeleton.get_bone_global_pose(bone_idx).origin
+ (_skeleton.global_transform.affine_inverse() * looked_at).basis.orthonormalized(),
+ _skeleton.get_bone_global_pose(_bone_idx).origin
)
)
func _w_look_at(from: Transform3D) -> Transform3D:
- # y look is default
- var w: Vector3 = from.basis.x
+ var w: Vector3
- if aim_axis == Axis.X_plus:
+ if aim_axis == Axis.Y_plus:
+ w = from.basis.x
+ elif aim_axis == Axis.X_plus:
w = from.basis.z
elif aim_axis == Axis.Z_plus:
w = from.basis.y
+ elif aim_axis == Axis.Y_minus:
+ w = w.inverse()
+ elif aim_axis == Axis.X_minus:
+ w = from.basis.y.inverse()
+ elif aim_axis == Axis.Z_minus:
+ w = from.basis.y.inverse()
- var t_v: Vector3 = target - from.origin
+ var t_v: Vector3 = target.global_position - from.origin
var v_y: Vector3 = t_v.normalized()
var v_z: Vector3 = w.cross(v_y)
v_z = v_z.normalized()