From e7326a924081cdec2e7ed1ba829aef95144be457 Mon Sep 17 00:00:00 2001 From: Silc 'Tokage' Renew Date: Sun, 12 Dec 2021 07:42:03 +0900 Subject: [PATCH] Refactored bone pose override in Skeleton3D --- doc/classes/BoneAttachment3D.xml | 13 -- doc/classes/Skeleton3D.xml | 66 ++++---- .../plugins/skeleton_ik_3d_editor_plugin.cpp | 1 - scene/3d/bone_attachment_3d.cpp | 42 +---- scene/3d/bone_attachment_3d.h | 8 - scene/3d/physics_body_3d.cpp | 4 +- scene/3d/skeleton_3d.cpp | 146 +++++++++--------- scene/3d/skeleton_3d.h | 65 ++++---- scene/3d/skeleton_ik_3d.cpp | 8 +- .../skeleton_modification_3d_ccdik.cpp | 6 +- .../skeleton_modification_3d_fabrik.cpp | 2 +- .../skeleton_modification_3d_jiggle.cpp | 6 +- .../skeleton_modification_3d_lookat.cpp | 4 +- .../skeleton_modification_3d_twoboneik.cpp | 20 +-- .../skeleton_modification_stack_3d.cpp | 2 +- 15 files changed, 172 insertions(+), 221 deletions(-) diff --git a/doc/classes/BoneAttachment3D.xml b/doc/classes/BoneAttachment3D.xml index bb4b45cd487a..f4b6ee0aa53e 100644 --- a/doc/classes/BoneAttachment3D.xml +++ b/doc/classes/BoneAttachment3D.xml @@ -16,12 +16,6 @@ Returns the [NodePath] to the external [Skeleton3D] node, if one has been set. - - - - Returns the override mode for the BoneAttachment3D node. - - @@ -48,13 +42,6 @@ Sets the [NodePath] to the external skeleton that the BoneAttachment3D node should use. The external [Skeleton3D] node is only used when [code]use_external_skeleton[/code] is set to [code]true[/code]. - - - - - Sets the override mode for the BoneAttachment3D node. The override mode defines which of the bone poses the BoneAttachment3D node will override. - - diff --git a/doc/classes/Skeleton3D.xml b/doc/classes/Skeleton3D.xml index 80a36acacc92..165fe56b8b38 100644 --- a/doc/classes/Skeleton3D.xml +++ b/doc/classes/Skeleton3D.xml @@ -29,22 +29,23 @@ This is useful for using the bone transform in calculations with transforms from [Node3D]-based nodes. - + + - Clear all the bones in this skeleton. + Removes the pose override on the bone at [code]bone_idx[/code]. - + - Removes the global pose override on all bones in the skeleton. + Removes the pose override on all bones in the skeleton. - + - Removes the local pose override on all bones in the skeleton. + Clear all the bones in this skeleton. @@ -113,13 +114,6 @@ - - - - - Returns the local pose override transform for [code]bone_idx[/code]. - - @@ -142,6 +136,20 @@ Returns the pose transform of the specified bone. Pose is applied on top of the custom pose, which is applied on top the rest pose. + + + + + Returns the pose without override transform for [code]bone_idx[/code]. + + + + + + + Returns the pose override transform for [code]bone_idx[/code]. + + @@ -185,7 +193,7 @@ Takes the passed-in global pose and converts it to local pose transform. - This can be used to easily convert a global pose from [method get_bone_global_pose] to a global transform in [method set_bone_local_pose_override]. + This can be used to easily convert a global pose from [method get_bone_global_pose] to a global transform in [method set_bone_pose_override]. @@ -212,6 +220,12 @@ Returns whether the bone pose for the bone at [code]bone_idx[/code] is enabled. + + + + + + @@ -294,25 +308,11 @@ - Sets the global pose transform, [code]pose[/code], for the bone at [code]bone_idx[/code]. - [code]amount[/code] is the interpolation strength that will be used when applying the pose, and [code]persistent[/code] determines if the applied pose will remain. [b]Note:[/b] The pose transform needs to be a global pose! Use [method world_transform_to_global_pose] to convert a world transform, like one you can get from a [Node3D], to a global pose. - - - - - - - - Sets the local pose transform, [code]pose[/code], for the bone at [code]bone_idx[/code]. - [code]amount[/code] is the interpolation strength that will be used when applying the pose, and [code]persistent[/code] determines if the applied pose will remain. - [b]Note:[/b] The pose transform needs to be a local pose! Use [method global_pose_to_local_pose] to convert a global pose to a local pose. - - @@ -329,6 +329,16 @@ [b]Note:[/b] [code]parent_idx[/code] must be less than [code]bone_idx[/code]. + + + + + + + Sets the local pose transform, [code]pose[/code], for the bone at [code]bone_idx[/code]. + [b]Note:[/b] The pose transform needs to be a local pose! Use [method global_pose_to_local_pose] to convert a global pose to a local pose. + + diff --git a/editor/plugins/skeleton_ik_3d_editor_plugin.cpp b/editor/plugins/skeleton_ik_3d_editor_plugin.cpp index 7dc34a0874b8..f0f54993aa98 100644 --- a/editor/plugins/skeleton_ik_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_ik_3d_editor_plugin.cpp @@ -46,7 +46,6 @@ void SkeletonIK3DEditorPlugin::_play() { skeleton_ik->start(); } else { skeleton_ik->stop(); - skeleton_ik->get_parent_skeleton()->clear_bones_global_pose_override(); } } diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp index 8623c7d8b631..03fa3f86e53e 100644 --- a/scene/3d/bone_attachment_3d.cpp +++ b/scene/3d/bone_attachment_3d.cpp @@ -65,8 +65,6 @@ void BoneAttachment3D::_validate_property(PropertyInfo &property) const { bool BoneAttachment3D::_set(const StringName &p_path, const Variant &p_value) { if (p_path == SNAME("override_pose")) { set_override_pose(p_value); - } else if (p_path == SNAME("override_mode")) { - set_override_mode(p_value); } else if (p_path == SNAME("use_external_skeleton")) { set_use_external_skeleton(p_value); } else if (p_path == SNAME("external_skeleton")) { @@ -79,8 +77,6 @@ bool BoneAttachment3D::_set(const StringName &p_path, const Variant &p_value) { bool BoneAttachment3D::_get(const StringName &p_path, Variant &r_ret) const { if (p_path == SNAME("override_pose")) { r_ret = get_override_pose(); - } else if (p_path == SNAME("override_mode")) { - r_ret = get_override_mode(); } else if (p_path == SNAME("use_external_skeleton")) { r_ret = get_use_external_skeleton(); } else if (p_path == SNAME("external_skeleton")) { @@ -92,9 +88,6 @@ bool BoneAttachment3D::_get(const StringName &p_path, Variant &r_ret) const { void BoneAttachment3D::_get_property_list(List *p_list) const { p_list->push_back(PropertyInfo(Variant::BOOL, "override_pose", PROPERTY_HINT_NONE, "")); - if (override_pose) { - p_list->push_back(PropertyInfo(Variant::INT, "override_mode", PROPERTY_HINT_ENUM, "Global Pose Override, Local Pose Override, Custom Pose")); - } p_list->push_back(PropertyInfo(Variant::BOOL, "use_external_skeleton", PROPERTY_HINT_NONE, "")); if (use_external_skeleton) { @@ -213,11 +206,7 @@ void BoneAttachment3D::_transform_changed() { our_trans = sk->world_transform_to_global_pose(get_global_transform()); } - if (override_mode == OVERRIDE_MODES::MODE_GLOBAL_POSE) { - sk->set_bone_global_pose_override(bone_idx, our_trans, 1.0, true); - } else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) { - sk->set_bone_local_pose_override(bone_idx, sk->global_pose_to_local_pose(bone_idx, our_trans), 1.0, true); - } + sk->set_bone_global_pose_override(bone_idx, our_trans, 1); } } @@ -269,11 +258,7 @@ void BoneAttachment3D::set_override_pose(bool p_override) { if (!override_pose) { Skeleton3D *sk = _get_skeleton3d(); if (sk) { - if (override_mode == OVERRIDE_MODES::MODE_GLOBAL_POSE) { - sk->set_bone_global_pose_override(bone_idx, Transform3D(), 0.0, false); - } else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) { - sk->set_bone_local_pose_override(bone_idx, Transform3D(), 0.0, false); - } + sk->clear_bone_pose_override(bone_idx); } _transform_changed(); } @@ -284,27 +269,6 @@ bool BoneAttachment3D::get_override_pose() const { return override_pose; } -void BoneAttachment3D::set_override_mode(int p_mode) { - if (override_pose) { - Skeleton3D *sk = _get_skeleton3d(); - if (sk) { - if (override_mode == OVERRIDE_MODES::MODE_GLOBAL_POSE) { - sk->set_bone_global_pose_override(bone_idx, Transform3D(), 0.0, false); - } else if (override_mode == OVERRIDE_MODES::MODE_LOCAL_POSE) { - sk->set_bone_local_pose_override(bone_idx, Transform3D(), 0.0, false); - } - } - override_mode = p_mode; - _transform_changed(); - return; - } - override_mode = p_mode; -} - -int BoneAttachment3D::get_override_mode() const { - return override_mode; -} - void BoneAttachment3D::set_use_external_skeleton(bool p_use_external) { use_external_skeleton = p_use_external; @@ -391,8 +355,6 @@ void BoneAttachment3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_override_pose", "override_pose"), &BoneAttachment3D::set_override_pose); ClassDB::bind_method(D_METHOD("get_override_pose"), &BoneAttachment3D::get_override_pose); - ClassDB::bind_method(D_METHOD("set_override_mode", "override_mode"), &BoneAttachment3D::set_override_mode); - ClassDB::bind_method(D_METHOD("get_override_mode"), &BoneAttachment3D::get_override_mode); ClassDB::bind_method(D_METHOD("set_use_external_skeleton", "use_external_skeleton"), &BoneAttachment3D::set_use_external_skeleton); ClassDB::bind_method(D_METHOD("get_use_external_skeleton"), &BoneAttachment3D::get_use_external_skeleton); diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h index 395dfde1d707..23a8d9bd6ad7 100644 --- a/scene/3d/bone_attachment_3d.h +++ b/scene/3d/bone_attachment_3d.h @@ -41,14 +41,8 @@ class BoneAttachment3D : public Node3D { int bone_idx = -1; bool override_pose = false; - int override_mode = 0; bool _override_dirty = false; - enum OVERRIDE_MODES { - MODE_GLOBAL_POSE, - MODE_LOCAL_POSE, - }; - bool use_external_skeleton = false; NodePath external_skeleton_node; ObjectID external_skeleton_node_cache; @@ -80,8 +74,6 @@ class BoneAttachment3D : public Node3D { void set_override_pose(bool p_override); bool get_override_pose() const; - void set_override_mode(int p_mode); - int get_override_mode() const; void set_use_external_skeleton(bool p_external_skeleton); bool get_use_external_skeleton() const; diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index c1f5ab1d3256..cec0ffa5c67f 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -2915,7 +2915,7 @@ void PhysicalBone3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) { // Update skeleton if (parent_skeleton) { if (-1 != bone_id) { - parent_skeleton->set_bone_global_pose_override(bone_id, parent_skeleton->get_global_transform().affine_inverse() * (global_transform * body_offset_inverse), 1.0, true); + parent_skeleton->set_bone_global_pose_override(bone_id, parent_skeleton->get_global_transform().affine_inverse() * (global_transform * body_offset_inverse), 1); } } } @@ -3429,7 +3429,7 @@ void PhysicalBone3D::_stop_physics_simulation() { } if (_internal_simulate_physics) { PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), nullptr, nullptr); - parent_skeleton->set_bone_global_pose_override(bone_id, Transform3D(), 0.0, false); + parent_skeleton->clear_bone_pose_override(bone_id); set_as_top_level(false); _internal_simulate_physics = false; } diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 598897456dfa..95576ed9f567 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -315,7 +315,7 @@ void Skeleton3D::_notification(int p_what) { for (uint32_t i = 0; i < bind_count; i++) { uint32_t bone_index = E->get()->skin_bone_indices_ptrs[i]; ERR_CONTINUE(bone_index >= (uint32_t)len); - rs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i)); + rs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].global_pose_cache * skin->get_bind_pose(i)); } } #ifdef TOOLS_ENABLED @@ -362,67 +362,76 @@ void Skeleton3D::_notification(int p_what) { } } -void Skeleton3D::clear_bones_global_pose_override() { - for (int i = 0; i < bones.size(); i += 1) { - bones.write[i].global_pose_override_amount = 0; - bones.write[i].global_pose_override_reset = true; +void Skeleton3D::clear_bone_pose_overrides() { + const int bone_size = bones.size(); + for (int i = 0; i < bone_size; i += 1) { + bones.write[i].is_override_enabled = false; + bones.write[i].pose_override = Transform3D(); + bones.write[i].pose_cache_dirty = true; } _make_dirty(); } -void Skeleton3D::set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, real_t p_amount, bool p_persistent) { +void Skeleton3D::clear_bone_pose_override(int p_bone) { const int bone_size = bones.size(); ERR_FAIL_INDEX(p_bone, bone_size); - bones.write[p_bone].global_pose_override_amount = p_amount; - bones.write[p_bone].global_pose_override = p_pose; - bones.write[p_bone].global_pose_override_reset = !p_persistent; + bones.write[p_bone].is_override_enabled = false; + bones.write[p_bone].pose_override = Transform3D(); + bones.write[p_bone].pose_cache_dirty = true; _make_dirty(); } -Transform3D Skeleton3D::get_bone_global_pose_override(int p_bone) const { +bool Skeleton3D::is_bone_pose_overridden(int p_bone) const { const int bone_size = bones.size(); - ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); - return bones[p_bone].global_pose_override; + ERR_FAIL_INDEX_V(p_bone, bone_size, false); + return bones[p_bone].is_override_enabled; } -Transform3D Skeleton3D::get_bone_global_pose(int p_bone) const { +Transform3D Skeleton3D::get_bone_pose_override(int p_bone) const { const int bone_size = bones.size(); ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); - if (dirty) { - const_cast(this)->notification(NOTIFICATION_UPDATE_SKELETON); - } - return bones[p_bone].pose_global; + return bones[p_bone].pose_override; } -Transform3D Skeleton3D::get_bone_global_pose_no_override(int p_bone) const { +void Skeleton3D::set_bone_pose_override(int p_bone, const Transform3D &p_pose, float p_amount) { + const int bone_size = bones.size(); + ERR_FAIL_INDEX(p_bone, bone_size); + bones.write[p_bone].is_override_enabled = true; + bones.write[p_bone].pose_override = get_bone_pose_no_override(p_bone).interpolate_with(p_pose, p_amount); + bones.write[p_bone].pose_cache_dirty = true; + _make_dirty(); +} + +Transform3D Skeleton3D::get_bone_global_pose_override(int p_bone) const { const int bone_size = bones.size(); ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); if (dirty) { const_cast(this)->notification(NOTIFICATION_UPDATE_SKELETON); } - return bones[p_bone].pose_global_no_override; + return const_cast(this)->local_pose_to_global_pose(p_bone, bones[p_bone].pose_override); } -void Skeleton3D::clear_bones_local_pose_override() { - for (int i = 0; i < bones.size(); i += 1) { - bones.write[i].local_pose_override_amount = 0; - } - _make_dirty(); +void Skeleton3D::set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, float p_amount) { + Transform3D tr = global_pose_to_local_pose(p_bone, p_pose); + set_bone_pose_override(p_bone, tr, p_amount); } -void Skeleton3D::set_bone_local_pose_override(int p_bone, const Transform3D &p_pose, real_t p_amount, bool p_persistent) { +Transform3D Skeleton3D::get_bone_global_pose(int p_bone) const { const int bone_size = bones.size(); - ERR_FAIL_INDEX(p_bone, bone_size); - bones.write[p_bone].local_pose_override_amount = p_amount; - bones.write[p_bone].local_pose_override = p_pose; - bones.write[p_bone].local_pose_override_reset = !p_persistent; - _make_dirty(); + ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); + if (dirty) { + const_cast(this)->notification(NOTIFICATION_UPDATE_SKELETON); + } + return bones[p_bone].global_pose_cache; } -Transform3D Skeleton3D::get_bone_local_pose_override(int p_bone) const { +Transform3D Skeleton3D::get_bone_global_pose_no_override(int p_bone) const { const int bone_size = bones.size(); ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); - return bones[p_bone].local_pose_override; + if (dirty) { + const_cast(this)->notification(NOTIFICATION_UPDATE_SKELETON); + } + return bones[p_bone].global_pose_no_override; } void Skeleton3D::update_bone_rest_forward_vector(int p_bone, bool p_force_update) { @@ -743,6 +752,12 @@ Transform3D Skeleton3D::get_bone_pose(int p_bone) const { return bones[p_bone].pose_cache; } +Transform3D Skeleton3D::get_bone_pose_no_override(int p_bone) const { + const int bone_size = bones.size(); + ERR_FAIL_INDEX_V(p_bone, bone_size, Transform3D()); + return bones[p_bone].pose; +} + void Skeleton3D::_make_dirty() { if (dirty) { return; @@ -1041,46 +1056,25 @@ void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) { if (bone_enabled) { b.update_pose_cache(); - Transform3D pose = b.pose_cache; + Transform3D current_pose = b.pose_cache; if (b.parent >= 0) { - b.pose_global = bonesptr[b.parent].pose_global * pose; - b.pose_global_no_override = b.pose_global; + b.global_pose_cache = bonesptr[b.parent].global_pose_cache * current_pose; + b.global_pose_no_override = bonesptr[b.parent].global_pose_no_override * b.pose; } else { - b.pose_global = pose; - b.pose_global_no_override = b.pose_global; + b.global_pose_cache = current_pose; + b.global_pose_no_override = b.pose; } } else { if (b.parent >= 0) { - b.pose_global = bonesptr[b.parent].pose_global * b.rest; - b.pose_global_no_override = b.pose_global; + b.global_pose_cache = bonesptr[b.parent].global_pose_cache * b.rest; + b.global_pose_no_override = bonesptr[b.parent].global_pose_no_override * b.rest; } else { - b.pose_global = b.rest; - b.pose_global_no_override = b.pose_global; + b.global_pose_cache = b.rest; + b.global_pose_no_override = b.rest; } } - if (b.local_pose_override_amount >= CMP_EPSILON) { - Transform3D override_local_pose; - if (b.parent >= 0) { - override_local_pose = bonesptr[b.parent].pose_global * b.local_pose_override; - } else { - override_local_pose = b.local_pose_override; - } - b.pose_global = b.pose_global.interpolate_with(override_local_pose, b.local_pose_override_amount); - } - - if (b.global_pose_override_amount >= CMP_EPSILON) { - b.pose_global = b.pose_global.interpolate_with(b.global_pose_override, b.global_pose_override_amount); - } - - if (b.local_pose_override_reset) { - b.local_pose_override_amount = 0.0; - } - if (b.global_pose_override_reset) { - b.global_pose_override_amount = 0.0; - } - // Add the bone's children to the list of bones to be processed. int child_bone_size = b.child_bones.size(); for (int i = 0; i < child_bone_size; i++) { @@ -1118,7 +1112,7 @@ Transform3D Skeleton3D::local_pose_to_global_pose(int p_bone_idx, Transform3D p_ ERR_FAIL_INDEX_V(p_bone_idx, bone_size, Transform3D()); if (bones[p_bone_idx].parent >= 0) { int parent_bone_idx = bones[p_bone_idx].parent; - return bones[parent_bone_idx].pose_global * p_local_pose; + return bones[parent_bone_idx].global_pose_cache * p_local_pose; } else { return p_local_pose; } @@ -1215,7 +1209,15 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_bones"), &Skeleton3D::clear_bones); + ClassDB::bind_method(D_METHOD("is_bone_enabled", "bone_idx"), &Skeleton3D::is_bone_enabled); + ClassDB::bind_method(D_METHOD("set_bone_enabled", "bone_idx", "enabled"), &Skeleton3D::set_bone_enabled, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("get_bone_pose", "bone_idx"), &Skeleton3D::get_bone_pose); + ClassDB::bind_method(D_METHOD("get_bone_pose_no_override", "bone_idx"), &Skeleton3D::get_bone_pose_no_override); + + ClassDB::bind_method(D_METHOD("get_bone_global_pose", "bone_idx"), &Skeleton3D::get_bone_global_pose); + ClassDB::bind_method(D_METHOD("get_bone_global_pose_no_override", "bone_idx"), &Skeleton3D::get_bone_global_pose_no_override); + ClassDB::bind_method(D_METHOD("set_bone_pose_position", "bone_idx", "position"), &Skeleton3D::set_bone_pose_position); ClassDB::bind_method(D_METHOD("set_bone_pose_rotation", "bone_idx", "rotation"), &Skeleton3D::set_bone_pose_rotation); ClassDB::bind_method(D_METHOD("set_bone_pose_scale", "bone_idx", "scale"), &Skeleton3D::set_bone_pose_scale); @@ -1224,18 +1226,16 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone_pose_rotation", "bone_idx"), &Skeleton3D::get_bone_pose_rotation); ClassDB::bind_method(D_METHOD("get_bone_pose_scale", "bone_idx"), &Skeleton3D::get_bone_pose_scale); - ClassDB::bind_method(D_METHOD("is_bone_enabled", "bone_idx"), &Skeleton3D::is_bone_enabled); - ClassDB::bind_method(D_METHOD("set_bone_enabled", "bone_idx", "enabled"), &Skeleton3D::set_bone_enabled, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("clear_bone_pose_overrides"), &Skeleton3D::clear_bone_pose_overrides); - ClassDB::bind_method(D_METHOD("clear_bones_global_pose_override"), &Skeleton3D::clear_bones_global_pose_override); - ClassDB::bind_method(D_METHOD("set_bone_global_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton3D::set_bone_global_pose_override, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("get_bone_global_pose_override", "bone_idx"), &Skeleton3D::get_bone_global_pose_override); - ClassDB::bind_method(D_METHOD("get_bone_global_pose", "bone_idx"), &Skeleton3D::get_bone_global_pose); - ClassDB::bind_method(D_METHOD("get_bone_global_pose_no_override", "bone_idx"), &Skeleton3D::get_bone_global_pose_no_override); + ClassDB::bind_method(D_METHOD("clear_bone_pose_override", "bone_idx"), &Skeleton3D::clear_bone_pose_override); + ClassDB::bind_method(D_METHOD("is_bone_pose_overridden", "bone_idx"), &Skeleton3D::is_bone_pose_overridden); + + ClassDB::bind_method(D_METHOD("set_bone_pose_override", "bone_idx", "pose", "amount"), &Skeleton3D::set_bone_pose_override); + ClassDB::bind_method(D_METHOD("get_bone_pose_override", "bone_idx"), &Skeleton3D::get_bone_pose_override); - ClassDB::bind_method(D_METHOD("clear_bones_local_pose_override"), &Skeleton3D::clear_bones_local_pose_override); - ClassDB::bind_method(D_METHOD("set_bone_local_pose_override", "bone_idx", "pose", "amount", "persistent"), &Skeleton3D::set_bone_local_pose_override, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("get_bone_local_pose_override", "bone_idx"), &Skeleton3D::get_bone_local_pose_override); + ClassDB::bind_method(D_METHOD("set_bone_global_pose_override", "bone_idx", "pose", "amount"), &Skeleton3D::set_bone_global_pose_override); + ClassDB::bind_method(D_METHOD("get_bone_global_pose_override", "bone_idx"), &Skeleton3D::get_bone_global_pose_override); ClassDB::bind_method(D_METHOD("force_update_all_bone_transforms"), &Skeleton3D::force_update_all_bone_transforms); ClassDB::bind_method(D_METHOD("force_update_bone_child_transform", "bone_idx"), &Skeleton3D::force_update_bone_children_transforms); diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index 80ff2a1f79e7..9d187d83e0ee 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -80,8 +80,13 @@ class Skeleton3D : public Node3D { _FORCE_INLINE_ void update_pose_cache() { if (pose_cache_dirty) { - pose_cache.basis.set_quaternion_scale(pose_rotation, pose_scale); - pose_cache.origin = pose_position; + pose.basis.set_quaternion_scale(pose_rotation, pose_scale); + pose.origin = pose_position; + if (is_override_enabled) { + pose_cache = pose_override; + } else { + pose_cache = pose; + } pose_cache_dirty = false; } } @@ -91,20 +96,18 @@ class Skeleton3D : public Node3D { Quaternion pose_rotation; Vector3 pose_scale = Vector3(1, 1, 1); - Transform3D pose_global; - Transform3D pose_global_no_override; + Transform3D pose; + Transform3D pose_override; + bool is_override_enabled = false; - real_t global_pose_override_amount = 0.0; - bool global_pose_override_reset = false; - Transform3D global_pose_override; + // The `global_pose` should be used for conversion to local from global coordinates in the setter. + // Since `global_pose_cache` is a cache, one shouldn't use `global_pose_cache` for display. + Transform3D global_pose_cache; + Transform3D global_pose_no_override; PhysicalBone3D *physical_bone = nullptr; PhysicalBone3D *cache_parent_physical_bone = nullptr; - real_t local_pose_override_amount; - bool local_pose_override_reset; - Transform3D local_pose_override; - Vector child_bones; // The forward direction vector and rest bone forward axis are cached because they do not change @@ -115,14 +118,10 @@ class Skeleton3D : public Node3D { Bone() { parent = -1; enabled = true; - global_pose_override_amount = 0; - global_pose_override_reset = false; #ifndef _3D_DISABLED physical_bone = nullptr; cache_parent_physical_bone = nullptr; #endif // _3D_DISABLED - local_pose_override_amount = 0; - local_pose_override_reset = false; child_bones = Vector(); rest_bone_forward_vector = Vector3(0, 0, 0); @@ -135,10 +134,10 @@ class Skeleton3D : public Node3D { void _skin_changed(); bool animate_physical_bones = true; - Vector bones; bool process_order_dirty; - Vector parentless_bones; + Vector bones = Vector(); + Vector parentless_bones = Vector(); void _make_dirty(); bool dirty = false; @@ -175,7 +174,7 @@ class Skeleton3D : public Node3D { NOTIFICATION_UPDATE_SKELETON = 50 }; - // skeleton creation api + // Skeleton creation API void add_bone(const String &p_name); int find_bone(const String &p_name) const; String get_bone_name(int p_bone) const; @@ -198,8 +197,6 @@ class Skeleton3D : public Node3D { void set_bone_rest(int p_bone, const Transform3D &p_rest); Transform3D get_bone_rest(int p_bone) const; - Transform3D get_bone_global_pose(int p_bone) const; - Transform3D get_bone_global_pose_no_override(int p_bone) const; void set_bone_enabled(int p_bone, bool p_enabled); bool is_bone_enabled(int p_bone) const; @@ -208,27 +205,34 @@ class Skeleton3D : public Node3D { bool is_show_rest_only() const; void clear_bones(); - // posing api - + // Posing api void set_bone_pose_position(int p_bone, const Vector3 &p_position); void set_bone_pose_rotation(int p_bone, const Quaternion &p_rotation); void set_bone_pose_scale(int p_bone, const Vector3 &p_scale); Transform3D get_bone_pose(int p_bone) const; + Transform3D get_bone_pose_no_override(int p_bone) const; + + Transform3D get_bone_global_pose(int p_bone) const; + Transform3D get_bone_global_pose_no_override(int p_bone) const; Vector3 get_bone_pose_position(int p_bone) const; Quaternion get_bone_pose_rotation(int p_bone) const; Vector3 get_bone_pose_scale(int p_bone) const; - void clear_bones_global_pose_override(); - Transform3D get_bone_global_pose_override(int p_bone) const; - void set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, real_t p_amount, bool p_persistent = false); + // Pose override + bool is_bone_pose_overridden(int p_bone) const; + void clear_bone_pose_override(int p_bone); + void clear_bone_pose_overrides(); - void clear_bones_local_pose_override(); - Transform3D get_bone_local_pose_override(int p_bone) const; - void set_bone_local_pose_override(int p_bone, const Transform3D &p_pose, real_t p_amount, bool p_persistent = false); + Transform3D get_bone_pose_override(int p_bone) const; + void set_bone_pose_override(int p_bone, const Transform3D &p_pose, float p_amount); - void localize_rests(); // used for loaders and tools + Transform3D get_bone_global_pose_override(int p_bone) const; + void set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, float p_amount); + + // Rest + void localize_rests(); // Used for loaders and tools. Ref create_skin_from_rest_transforms(); @@ -259,7 +263,6 @@ class Skeleton3D : public Node3D { #endif // _3D_DISABLED // Physical bone API - void set_animate_physical_bones(bool p_enabled); bool get_animate_physical_bones() const; @@ -270,7 +273,7 @@ class Skeleton3D : public Node3D { PhysicalBone3D *get_physical_bone_parent(int p_bone); private: - /// This is a slow API, so it's cached + /// This is a slow API, so it's cached. PhysicalBone3D *_get_physical_bone_parent(int p_bone); void _rebuild_physical_bones_cache(); diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp index f29b06006997..9e5f2285fdd2 100644 --- a/scene/3d/skeleton_ik_3d.cpp +++ b/scene/3d/skeleton_ik_3d.cpp @@ -254,7 +254,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove // Before skipping, make sure we undo the global pose overrides ChainItem *ci(&p_task->chain.chain_root); while (ci) { - p_task->skeleton->set_bone_global_pose_override(ci->bone, ci->initial_transform, 0.0, false); + p_task->skeleton->clear_bone_pose_override(ci->bone); if (!ci->children.is_empty()) { ci = &ci->children.write[0]; @@ -269,7 +269,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove // Update the initial root transform so its synced with any animation changes _update_chain(p_task->skeleton, &p_task->chain.chain_root); - p_task->skeleton->set_bone_global_pose_override(p_task->chain.chain_root.bone, Transform3D(), 0.0, false); + p_task->skeleton->clear_bone_pose_override(p_task->chain.chain_root.bone); Vector3 origin_pos = p_task->skeleton->get_bone_global_pose(p_task->chain.chain_root.bone).origin; make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse(), blending_delta); @@ -305,7 +305,7 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove new_bone_pose.basis.orthonormalize(); new_bone_pose.basis.scale(p_task->skeleton->get_bone_global_pose(ci->bone).basis.get_scale()); - p_task->skeleton->set_bone_global_pose_override(ci->bone, new_bone_pose, 1.0, true); + p_task->skeleton->set_bone_global_pose_override(ci->bone, new_bone_pose, 1); if (!ci->children.is_empty()) { ci = &ci->children.write[0]; @@ -527,7 +527,7 @@ void SkeletonIK3D::start(bool p_one_time) { void SkeletonIK3D::stop() { set_process_internal(false); if (skeleton) { - skeleton->clear_bones_global_pose_override(); + skeleton->clear_bone_pose_overrides(); } } diff --git a/scene/resources/skeleton_modification_3d_ccdik.cpp b/scene/resources/skeleton_modification_3d_ccdik.cpp index f19be47db25f..0c660e27ba6b 100644 --- a/scene/resources/skeleton_modification_3d_ccdik.cpp +++ b/scene/resources/skeleton_modification_3d_ccdik.cpp @@ -129,9 +129,7 @@ void SkeletonModification3DCCDIK::_execute(real_t p_delta) { // Reset the local bone overrides for CCDIK affected nodes for (uint32_t i = 0; i < ccdik_data_chain.size(); i++) { - stack->skeleton->set_bone_local_pose_override(ccdik_data_chain[i].bone_idx, - stack->skeleton->get_bone_local_pose_override(ccdik_data_chain[i].bone_idx), - 0.0, false); + stack->skeleton->clear_bone_pose_override(ccdik_data_chain[i].bone_idx); } Node3D *node_target = Object::cast_to(ObjectDB::get_instance(target_node_cache)); @@ -228,7 +226,7 @@ void SkeletonModification3DCCDIK::_execute_ccdik_joint(int p_joint_idx, Node3D * bone_trans.basis.set_axis_angle(rotation_axis, rotation_angle); } - stack->skeleton->set_bone_local_pose_override(ccdik_data.bone_idx, bone_trans, stack->strength, true); + stack->skeleton->set_bone_pose_override(ccdik_data.bone_idx, bone_trans, stack->strength); stack->skeleton->force_update_bone_children_transforms(ccdik_data.bone_idx); } diff --git a/scene/resources/skeleton_modification_3d_fabrik.cpp b/scene/resources/skeleton_modification_3d_fabrik.cpp index b62dda3f4fa4..1513b022b42d 100644 --- a/scene/resources/skeleton_modification_3d_fabrik.cpp +++ b/scene/resources/skeleton_modification_3d_fabrik.cpp @@ -285,7 +285,7 @@ void SkeletonModification3DFABRIK::chain_apply() { current_trans.basis.rotate_to_align(forward_vector, current_trans.origin.direction_to(next_trans.origin)); current_trans.basis.rotate_local(forward_vector, fabrik_data_chain[i].roll); } - stack->skeleton->set_bone_local_pose_override(current_bone_idx, stack->skeleton->global_pose_to_local_pose(current_bone_idx, current_trans), stack->strength, true); + stack->skeleton->set_bone_global_pose_override(current_bone_idx, current_trans, stack->strength); } // Update all the bones so the next modification has up-to-date data. diff --git a/scene/resources/skeleton_modification_3d_jiggle.cpp b/scene/resources/skeleton_modification_3d_jiggle.cpp index 3e36c241f78c..211150a4adaf 100644 --- a/scene/resources/skeleton_modification_3d_jiggle.cpp +++ b/scene/resources/skeleton_modification_3d_jiggle.cpp @@ -172,7 +172,7 @@ void SkeletonModification3DJiggle::_execute_jiggle_joint(int p_joint_idx, Node3D return; } - Transform3D bone_local_pos = stack->skeleton->get_bone_local_pose_override(jiggle_data_chain[p_joint_idx].bone_idx); + Transform3D bone_local_pos = stack->skeleton->get_bone_pose_override(jiggle_data_chain[p_joint_idx].bone_idx); if (bone_local_pos == Transform3D()) { bone_local_pos = stack->skeleton->get_bone_pose(jiggle_data_chain[p_joint_idx].bone_idx); } @@ -237,7 +237,7 @@ void SkeletonModification3DJiggle::_execute_jiggle_joint(int p_joint_idx, Node3D new_bone_trans.basis.rotate_local(forward_vector, jiggle_data_chain[p_joint_idx].roll); new_bone_trans = stack->skeleton->global_pose_to_local_pose(jiggle_data_chain[p_joint_idx].bone_idx, new_bone_trans); - stack->skeleton->set_bone_local_pose_override(jiggle_data_chain[p_joint_idx].bone_idx, new_bone_trans, stack->strength, true); + stack->skeleton->set_bone_pose_override(jiggle_data_chain[p_joint_idx].bone_idx, new_bone_trans, stack->strength); stack->skeleton->force_update_bone_children_transforms(jiggle_data_chain[p_joint_idx].bone_idx); } @@ -264,7 +264,7 @@ void SkeletonModification3DJiggle::_setup_modification(SkeletonModificationStack for (uint32_t i = 0; i < jiggle_data_chain.size(); i++) { int bone_idx = jiggle_data_chain[i].bone_idx; if (bone_idx > 0 && bone_idx < stack->skeleton->get_bone_count()) { - jiggle_data_chain[i].dynamic_position = stack->skeleton->local_pose_to_global_pose(bone_idx, stack->skeleton->get_bone_local_pose_override(bone_idx)).origin; + jiggle_data_chain[i].dynamic_position = stack->skeleton->get_bone_global_pose_override(bone_idx).origin; } } } diff --git a/scene/resources/skeleton_modification_3d_lookat.cpp b/scene/resources/skeleton_modification_3d_lookat.cpp index 3e8c1e3a7729..5c5670f336e4 100644 --- a/scene/resources/skeleton_modification_3d_lookat.cpp +++ b/scene/resources/skeleton_modification_3d_lookat.cpp @@ -96,7 +96,7 @@ void SkeletonModification3DLookAt::_execute(real_t p_delta) { if (_print_execution_error(bone_idx <= -1, "Bone index is invalid. Cannot execute modification!")) { return; } - Transform3D new_bone_trans = stack->skeleton->get_bone_local_pose_override(bone_idx); + Transform3D new_bone_trans = stack->skeleton->get_bone_pose_override(bone_idx); if (new_bone_trans == Transform3D()) { new_bone_trans = stack->skeleton->get_bone_pose(bone_idx); } @@ -124,7 +124,7 @@ void SkeletonModification3DLookAt::_execute(real_t p_delta) { new_bone_trans.basis.rotate_local(Vector3(0, 1, 0), additional_rotation.y); new_bone_trans.basis.rotate_local(Vector3(0, 0, 1), additional_rotation.z); - stack->skeleton->set_bone_local_pose_override(bone_idx, new_bone_trans, stack->strength, true); + stack->skeleton->set_bone_pose_override(bone_idx, new_bone_trans, stack->strength); stack->skeleton->force_update_bone_children_transforms(bone_idx); // If we completed it successfully, then we can set execution_error_found to false diff --git a/scene/resources/skeleton_modification_3d_twoboneik.cpp b/scene/resources/skeleton_modification_3d_twoboneik.cpp index acc5ff716ce3..2121626f279a 100644 --- a/scene/resources/skeleton_modification_3d_twoboneik.cpp +++ b/scene/resources/skeleton_modification_3d_twoboneik.cpp @@ -178,11 +178,11 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) { } Transform3D pole_trans = stack->skeleton->world_transform_to_global_pose(pole->get_global_transform()); - Transform3D bone_one_local_pos = stack->skeleton->get_bone_local_pose_override(joint_one_bone_idx); + Transform3D bone_one_local_pos = stack->skeleton->get_bone_pose_override(joint_one_bone_idx); if (bone_one_local_pos == Transform3D()) { bone_one_local_pos = stack->skeleton->get_bone_pose(joint_one_bone_idx); } - Transform3D bone_two_local_pos = stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx); + Transform3D bone_two_local_pos = stack->skeleton->get_bone_pose_override(joint_two_bone_idx); if (bone_two_local_pos == Transform3D()) { bone_two_local_pos = stack->skeleton->get_bone_pose(joint_two_bone_idx); } @@ -192,7 +192,7 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) { bone_one_trans.basis = stack->skeleton->global_pose_z_forward_to_bone_forward(joint_one_bone_idx, bone_one_trans.basis); stack->skeleton->update_bone_rest_forward_vector(joint_one_bone_idx); bone_one_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_one_bone_idx), joint_one_roll); - stack->skeleton->set_bone_local_pose_override(joint_one_bone_idx, stack->skeleton->global_pose_to_local_pose(joint_one_bone_idx, bone_one_trans), stack->strength, true); + stack->skeleton->set_bone_global_pose_override(joint_one_bone_idx, bone_one_trans, stack->strength); stack->skeleton->force_update_bone_children_transforms(joint_one_bone_idx); bone_two_trans = stack->skeleton->local_pose_to_global_pose(joint_two_bone_idx, bone_two_local_pos); @@ -200,14 +200,14 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) { bone_two_trans.basis = stack->skeleton->global_pose_z_forward_to_bone_forward(joint_two_bone_idx, bone_two_trans.basis); stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx); bone_two_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx), joint_two_roll); - stack->skeleton->set_bone_local_pose_override(joint_two_bone_idx, stack->skeleton->global_pose_to_local_pose(joint_two_bone_idx, bone_two_trans), stack->strength, true); + stack->skeleton->set_bone_global_pose_override(joint_two_bone_idx, bone_two_trans, stack->strength); stack->skeleton->force_update_bone_children_transforms(joint_two_bone_idx); } else { - Transform3D bone_one_local_pos = stack->skeleton->get_bone_local_pose_override(joint_one_bone_idx); + Transform3D bone_one_local_pos = stack->skeleton->get_bone_pose_override(joint_one_bone_idx); if (bone_one_local_pos == Transform3D()) { bone_one_local_pos = stack->skeleton->get_bone_pose(joint_one_bone_idx); } - Transform3D bone_two_local_pos = stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx); + Transform3D bone_two_local_pos = stack->skeleton->get_bone_pose_override(joint_two_bone_idx); if (bone_two_local_pos == Transform3D()) { bone_two_local_pos = stack->skeleton->get_bone_pose(joint_two_bone_idx); } @@ -269,12 +269,12 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) { // Apply the rotation to the first joint bone_one_trans = stack->skeleton->global_pose_to_local_pose(joint_one_bone_idx, bone_one_trans); bone_one_trans.origin = Vector3(0, 0, 0); - stack->skeleton->set_bone_local_pose_override(joint_one_bone_idx, bone_one_trans, stack->strength, true); + stack->skeleton->set_bone_pose_override(joint_one_bone_idx, bone_one_trans, stack->strength); stack->skeleton->force_update_bone_children_transforms(joint_one_bone_idx); if (use_pole_node) { // Update bone_two_trans so its at the latest position, with the rotation of bone_one_trans taken into account, then look at the target. - bone_two_trans = stack->skeleton->local_pose_to_global_pose(joint_two_bone_idx, stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx)); + bone_two_trans = stack->skeleton->local_pose_to_global_pose(joint_two_bone_idx, stack->skeleton->get_bone_pose_override(joint_two_bone_idx)); stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx); Vector3 forward_vector = stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx); bone_two_trans.basis.rotate_to_align(forward_vector, bone_two_trans.origin.direction_to(target_trans.origin)); @@ -283,7 +283,7 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) { bone_two_trans.basis.rotate_local(stack->skeleton->get_bone_axis_forward_vector(joint_two_bone_idx), joint_two_roll); bone_two_trans = stack->skeleton->global_pose_to_local_pose(joint_two_bone_idx, bone_two_trans); - stack->skeleton->set_bone_local_pose_override(joint_two_bone_idx, bone_two_trans, stack->strength, true); + stack->skeleton->set_bone_pose_override(joint_two_bone_idx, bone_two_trans, stack->strength); stack->skeleton->force_update_bone_children_transforms(joint_two_bone_idx); } else { // Calculate the angles for the second joint using the law of cosigns, make a quaternion with the delta rotation needed to rotate the joint into @@ -299,7 +299,7 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) { bone_two_trans = stack->skeleton->global_pose_to_local_pose(joint_two_bone_idx, bone_two_trans); bone_two_trans.origin = Vector3(0, 0, 0); - stack->skeleton->set_bone_local_pose_override(joint_two_bone_idx, bone_two_trans, stack->strength, true); + stack->skeleton->set_bone_pose_override(joint_two_bone_idx, bone_two_trans, stack->strength); stack->skeleton->force_update_bone_children_transforms(joint_two_bone_idx); } } diff --git a/scene/resources/skeleton_modification_stack_3d.cpp b/scene/resources/skeleton_modification_stack_3d.cpp index 7ccba1228c29..ce8c33e60c68 100644 --- a/scene/resources/skeleton_modification_stack_3d.cpp +++ b/scene/resources/skeleton_modification_stack_3d.cpp @@ -174,7 +174,7 @@ void SkeletonModificationStack3D::set_enabled(bool p_enabled) { enabled = p_enabled; if (!enabled && is_setup && skeleton != nullptr) { - skeleton->clear_bones_local_pose_override(); + skeleton->clear_bone_pose_overrides(); } }