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;