From 17d068963ff2e2131497b1b5d77c8cd5a5895ecb Mon Sep 17 00:00:00 2001
From: "Silc Lizard (Tokage) Renew"
<61938263+TokageItLab@users.noreply.github.com>
Date: Tue, 25 Mar 2025 01:37:25 +0900
Subject: [PATCH] Add bone name/idx matching validation & virtual func to skel
Modifier
---
doc/classes/SkeletonModifier3D.xml | 14 ++++++++++++++
scene/3d/look_at_modifier_3d.cpp | 16 +++++++++++++++-
scene/3d/look_at_modifier_3d.h | 2 ++
scene/3d/skeleton_modifier_3d.cpp | 12 +++++++++++-
scene/3d/skeleton_modifier_3d.h | 3 +++
scene/3d/spring_bone_collision_3d.cpp | 18 ++++++++++++++++++
scene/3d/spring_bone_collision_3d.h | 3 +++
scene/3d/spring_bone_simulator_3d.cpp | 17 +++++++++++++++++
scene/3d/spring_bone_simulator_3d.h | 2 ++
9 files changed, 85 insertions(+), 2 deletions(-)
diff --git a/doc/classes/SkeletonModifier3D.xml b/doc/classes/SkeletonModifier3D.xml
index c33a79c5ed8..2e633815a52 100644
--- a/doc/classes/SkeletonModifier3D.xml
+++ b/doc/classes/SkeletonModifier3D.xml
@@ -28,6 +28,20 @@
[param delta] is passed from parent [Skeleton3D]. See also [method Skeleton3D.advance].
+
+
+
+
+
+ Called when the skeleton is changed.
+
+
+
+
+
+ Called when bone name and index need to be validated such as the timing of the entering tree or changing skeleton.
+
+
diff --git a/scene/3d/look_at_modifier_3d.cpp b/scene/3d/look_at_modifier_3d.cpp
index ea17f5a76a4..0d9852759d2 100644
--- a/scene/3d/look_at_modifier_3d.cpp
+++ b/scene/3d/look_at_modifier_3d.cpp
@@ -75,6 +75,20 @@ PackedStringArray LookAtModifier3D::get_configuration_warnings() const {
return warnings;
}
+void LookAtModifier3D::_validate_bone_names() {
+ // Prior bone name.
+ if (!bone_name.is_empty()) {
+ set_bone_name(bone_name);
+ } else if (bone != -1) {
+ set_bone(bone);
+ }
+ if (!origin_bone_name.is_empty()) {
+ set_origin_bone_name(origin_bone_name);
+ } else if (origin_bone != -1) {
+ set_origin_bone(origin_bone);
+ }
+}
+
void LookAtModifier3D::set_bone_name(const String &p_bone_name) {
bone_name = p_bone_name;
Skeleton3D *sk = get_skeleton();
@@ -529,7 +543,7 @@ void LookAtModifier3D::_process_modification(double p_delta) {
} else {
origin_tr = bone_rest_space;
}
- forward_vector = bone_rest_space.orthonormalized().basis.xform_inv((target->get_global_position() - origin_tr.translated_local(origin_offset).origin));
+ forward_vector = bone_rest_space.orthonormalized().basis.xform_inv(target->get_global_position() - origin_tr.translated_local(origin_offset).origin);
forward_vector_nrm = forward_vector.normalized();
if (forward_vector_nrm.abs().is_equal_approx(get_vector_from_axis(primary_rotation_axis))) {
destination = skeleton->get_bone_pose_rotation(bone);
diff --git a/scene/3d/look_at_modifier_3d.h b/scene/3d/look_at_modifier_3d.h
index f56cdfa5da8..f75bad47fa8 100644
--- a/scene/3d/look_at_modifier_3d.h
+++ b/scene/3d/look_at_modifier_3d.h
@@ -105,6 +105,8 @@ protected:
virtual PackedStringArray get_configuration_warnings() const override;
void _validate_property(PropertyInfo &p_property) const;
+ virtual void _validate_bone_names() override;
+
static void _bind_methods();
virtual void _process_modification(double p_delta) override;
diff --git a/scene/3d/skeleton_modifier_3d.cpp b/scene/3d/skeleton_modifier_3d.cpp
index ccbc65066c1..1fae89b850d 100644
--- a/scene/3d/skeleton_modifier_3d.cpp
+++ b/scene/3d/skeleton_modifier_3d.cpp
@@ -68,11 +68,18 @@ void SkeletonModifier3D::_update_skeleton() {
if (old_sk != new_sk) {
_skeleton_changed(old_sk, new_sk);
}
+ if (new_sk) {
+ _validate_bone_names();
+ }
update_configuration_warnings();
}
void SkeletonModifier3D::_skeleton_changed(Skeleton3D *p_old, Skeleton3D *p_new) {
- //
+ GDVIRTUAL_CALL(_skeleton_changed, p_old, p_new);
+}
+
+void SkeletonModifier3D::_validate_bone_names() {
+ GDVIRTUAL_CALL(_validate_bone_names);
}
void SkeletonModifier3D::_force_update_skeleton_skin() {
@@ -163,6 +170,9 @@ void SkeletonModifier3D::_bind_methods() {
GDVIRTUAL_BIND(_process_modification);
#endif
+ GDVIRTUAL_BIND(_skeleton_changed, "old_skeleton", "new_skeleton");
+ GDVIRTUAL_BIND(_validate_bone_names);
+
BIND_ENUM_CONSTANT(BONE_AXIS_PLUS_X);
BIND_ENUM_CONSTANT(BONE_AXIS_MINUS_X);
BIND_ENUM_CONSTANT(BONE_AXIS_PLUS_Y);
diff --git a/scene/3d/skeleton_modifier_3d.h b/scene/3d/skeleton_modifier_3d.h
index 7710539c11e..00f851c09ec 100644
--- a/scene/3d/skeleton_modifier_3d.h
+++ b/scene/3d/skeleton_modifier_3d.h
@@ -61,6 +61,9 @@ protected:
void _force_update_skeleton_skin();
virtual void _skeleton_changed(Skeleton3D *p_old, Skeleton3D *p_new);
+ virtual void _validate_bone_names();
+ GDVIRTUAL2(_skeleton_changed, Skeleton3D *, Skeleton3D *);
+ GDVIRTUAL0(_validate_bone_names);
void _validate_property(PropertyInfo &p_property) const;
void _notification(int p_what);
diff --git a/scene/3d/spring_bone_collision_3d.cpp b/scene/3d/spring_bone_collision_3d.cpp
index 76ea1a373d3..32130aeca8d 100644
--- a/scene/3d/spring_bone_collision_3d.cpp
+++ b/scene/3d/spring_bone_collision_3d.cpp
@@ -58,6 +58,15 @@ void SpringBoneCollision3D::_validate_property(PropertyInfo &p_property) const {
}
}
+void SpringBoneCollision3D::_validate_bone_name() {
+ // Prior bone name.
+ if (!bone_name.is_empty()) {
+ set_bone_name(bone_name);
+ } else if (bone != -1) {
+ set_bone(bone);
+ }
+}
+
Skeleton3D *SpringBoneCollision3D::get_skeleton() const {
SpringBoneSimulator3D *parent = Object::cast_to(get_parent());
if (!parent) {
@@ -173,6 +182,15 @@ void SpringBoneCollision3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "rotation_offset"), "set_rotation_offset", "get_rotation_offset");
}
+void SpringBoneCollision3D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_PARENTED: {
+ _validate_bone_name();
+ } break;
+ }
+}
+
Vector3 SpringBoneCollision3D::collide(const Transform3D &p_center, float p_bone_radius, float p_bone_length, const Vector3 &p_current) const {
return _collide(p_center, p_bone_radius, p_bone_length, p_current);
}
diff --git a/scene/3d/spring_bone_collision_3d.h b/scene/3d/spring_bone_collision_3d.h
index 9121eb34e71..e27531489ab 100644
--- a/scene/3d/spring_bone_collision_3d.h
+++ b/scene/3d/spring_bone_collision_3d.h
@@ -41,10 +41,13 @@ class SpringBoneCollision3D : public Node3D {
Vector3 position_offset;
Quaternion rotation_offset;
+ void _validate_bone_name();
+
protected:
PackedStringArray get_configuration_warnings() const override;
void _validate_property(PropertyInfo &p_property) const;
+ void _notification(int p_what);
static void _bind_methods();
virtual Vector3 _collide(const Transform3D &p_center, float p_bone_radius, float p_bone_length, const Vector3 &p_current) const;
diff --git a/scene/3d/spring_bone_simulator_3d.cpp b/scene/3d/spring_bone_simulator_3d.cpp
index 605fcc1cfe0..3e539a9cb98 100644
--- a/scene/3d/spring_bone_simulator_3d.cpp
+++ b/scene/3d/spring_bone_simulator_3d.cpp
@@ -1240,6 +1240,23 @@ void SpringBoneSimulator3D::_bind_methods() {
BIND_ENUM_CONSTANT(ROTATION_AXIS_ALL);
}
+void SpringBoneSimulator3D::_validate_bone_names() {
+ for (int i = 0; i < settings.size(); i++) {
+ // Prior bone name.
+ if (!settings[i]->root_bone_name.is_empty()) {
+ set_root_bone_name(i, settings[i]->root_bone_name);
+ } else if (settings[i]->root_bone != -1) {
+ set_root_bone(i, settings[i]->root_bone);
+ }
+ // Prior bone name.
+ if (!settings[i]->end_bone_name.is_empty()) {
+ set_end_bone_name(i, settings[i]->end_bone_name);
+ } else if (settings[i]->end_bone != -1) {
+ set_end_bone(i, settings[i]->end_bone);
+ }
+ }
+}
+
void SpringBoneSimulator3D::_make_joints_dirty(int p_index) {
ERR_FAIL_INDEX(p_index, settings.size());
settings[p_index]->joints_dirty = true;
diff --git a/scene/3d/spring_bone_simulator_3d.h b/scene/3d/spring_bone_simulator_3d.h
index d2398b080ac..aee904623ad 100644
--- a/scene/3d/spring_bone_simulator_3d.h
+++ b/scene/3d/spring_bone_simulator_3d.h
@@ -150,6 +150,8 @@ protected:
void _notification(int p_what);
+ virtual void _validate_bone_names() override;
+
static void _bind_methods();
virtual void _set_active(bool p_active) override;