Files
mtgodot-poc/project/fx/motion_effect_anchor.gd

41 lines
1.5 KiB
GDScript

# 40250 ActorInstanceMotionEvent / ActorInstanceAttach: bone * offset * actor
# in row-vector order. The Godot equivalent is actor * offset * bone.
extends Node
const SOURCE_TO_METRES := Transform3D(Basis(Vector3(0.01, 0, 0), Vector3(0, 0, -0.01), Vector3(0, 0.01, 0)), Vector3.ZERO)
var model: Node3D
var animator: Node
var event := {}
func configure(view: Node3D, data: Dictionary) -> bool:
model = view.get("model")
animator = view.get("anim")
event = data.duplicate()
# Sample immediately, then after animation (default priority 0) every frame.
process_priority = 100
if not update_anchor():
return false
var attached := bool(event.get("attaching", false))
set_process(not bool(event.get("independent", false)) and
(not attached or bool(event.get("following", false))))
return true
func update_anchor() -> bool:
if not is_instance_valid(model) or not model.is_inside_tree():
return false
var bone := Transform3D.IDENTITY
if bool(event.get("attaching", false)) and not bool(event.get("independent", false)):
if not is_instance_valid(animator):
return false
var pose: Dictionary = animator.get_effect_bone_pose(String(event.get("bone", "")))
if pose.is_empty():
return false # No silent substitution of the actor origin for a missing bone.
bone = pose.transform
var offset := Transform3D(Basis.IDENTITY, event.get("pos", Vector3.ZERO))
get_parent().global_transform = model.global_transform * offset * bone * SOURCE_TO_METRES.affine_inverse()
return true
func _process(_delta: float) -> void:
if not update_anchor():
get_parent().queue_free()