From 907c726d3bf44c0b7c337905e72d6f28ba3b5a12 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
(cherry picked from commit 17d068963ff2e2131497b1b5d77c8cd5a5895ecb)
---
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 7e9814b16f..7fc0c96f32 100644
--- a/doc/classes/SkeletonModifier3D.xml
+++ b/doc/classes/SkeletonModifier3D.xml
@@ -19,6 +19,20 @@
[method _process_modification] must not apply [member influence] to bone poses because the [Skeleton3D] automatically applies influence to all bone poses set by the modifier.
+
+
+
+
+
+ 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 4bbb4450ff..b33985fdb1 100644
--- a/scene/3d/look_at_modifier_3d.cpp
+++ b/scene/3d/look_at_modifier_3d.cpp
@@ -77,6 +77,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();
@@ -531,7 +545,7 @@ void LookAtModifier3D::_process_modification() {
} 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 1c11661607..512fb93c7e 100644
--- a/scene/3d/look_at_modifier_3d.h
+++ b/scene/3d/look_at_modifier_3d.h
@@ -108,6 +108,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() override;
diff --git a/scene/3d/skeleton_modifier_3d.cpp b/scene/3d/skeleton_modifier_3d.cpp
index 3e3e5a9949..727869e11e 100644
--- a/scene/3d/skeleton_modifier_3d.cpp
+++ b/scene/3d/skeleton_modifier_3d.cpp
@@ -70,11 +70,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() {
@@ -155,6 +162,9 @@ void SkeletonModifier3D::_bind_methods() {
ADD_SIGNAL(MethodInfo("modification_processed"));
GDVIRTUAL_BIND(_process_modification);
+ 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 4b862ed034..cd9080d0df 100644
--- a/scene/3d/skeleton_modifier_3d.h
+++ b/scene/3d/skeleton_modifier_3d.h
@@ -64,6 +64,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 2b48c8acec..5453bc2d82 100644
--- a/scene/3d/spring_bone_collision_3d.cpp
+++ b/scene/3d/spring_bone_collision_3d.cpp
@@ -60,6 +60,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) {
@@ -175,6 +184,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 b3a5fd9f64..c789aee2b4 100644
--- a/scene/3d/spring_bone_collision_3d.h
+++ b/scene/3d/spring_bone_collision_3d.h
@@ -44,10 +44,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 13359c88a2..dd5e1ba4c5 100644
--- a/scene/3d/spring_bone_simulator_3d.cpp
+++ b/scene/3d/spring_bone_simulator_3d.cpp
@@ -1215,6 +1215,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 e2c9df027d..8480907e96 100644
--- a/scene/3d/spring_bone_simulator_3d.h
+++ b/scene/3d/spring_bone_simulator_3d.h
@@ -152,6 +152,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;