diff --git a/modules/many_bone_ik/doc_classes/IKBoneSegment3D.xml b/modules/many_bone_ik/doc_classes/IKBoneSegment3D.xml
index 1ddf26131a36..8f5eda17737a 100644
--- a/modules/many_bone_ik/doc_classes/IKBoneSegment3D.xml
+++ b/modules/many_bone_ik/doc_classes/IKBoneSegment3D.xml
@@ -7,7 +7,7 @@
-
+
diff --git a/modules/many_bone_ik/editor/many_bone_ik_3d_gizmo_plugin.cpp b/modules/many_bone_ik/editor/many_bone_ik_3d_gizmo_plugin.cpp
index ce254010cf64..68292f4860d8 100644
--- a/modules/many_bone_ik/editor/many_bone_ik_3d_gizmo_plugin.cpp
+++ b/modules/many_bone_ik/editor/many_bone_ik_3d_gizmo_plugin.cpp
@@ -30,6 +30,7 @@
#include "many_bone_ik_3d_gizmo_plugin.h"
+#include "core/variant/typed_array.h"
#include "modules/many_bone_ik/src/ik_kusudama_3d.h"
#include "core/io/resource_saver.h"
@@ -97,8 +98,9 @@ void ManyBoneIK3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Vector bones_to_process = many_bone_ik_skeleton->get_parentless_bones();
int bones_to_process_i = 0;
Vector processing_bones;
- Vector[> bone_segments = many_bone_ik->get_segmented_skeletons();
- for (Ref bone_segment : bone_segments) {
+ TypedArray bone_segments = many_bone_ik->get_child_segments();
+ for (int32_t segment_i = 0; segment_i < bone_segments.size(); segment_i++) {
+ Ref bone_segment = bone_segments[segment_i];
if (bone_segment.is_null()) {
continue;
}
@@ -113,7 +115,7 @@ void ManyBoneIK3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
}
Color current_bone_color = bone_color;
for (BoneId bone_i : bones_to_process) {
- Ref ik_bone = bone_segment->get_ik_bone(bone_i);
+ Ref ik_bone = bone_segment->find_ik_bone(bone_i);
if (ik_bone.is_null()) {
continue;
}
diff --git a/modules/many_bone_ik/editor/many_bone_ik_3d_handle_gizmo_plugin.cpp b/modules/many_bone_ik/editor/many_bone_ik_3d_handle_gizmo_plugin.cpp
index 08fb59be6b81..2f1da2e24ef2 100644
--- a/modules/many_bone_ik/editor/many_bone_ik_3d_handle_gizmo_plugin.cpp
+++ b/modules/many_bone_ik/editor/many_bone_ik_3d_handle_gizmo_plugin.cpp
@@ -97,8 +97,9 @@ void ManyBoneIK3DHandleGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Vector bones_to_process = many_bone_ik_skeleton->get_parentless_bones();
int bones_to_process_i = 0;
Vector processing_bones;
- Vector][> bone_segments = many_bone_ik->get_segmented_skeletons();
- for (Ref bone_segment : bone_segments) {
+ TypedArray bone_segments = many_bone_ik->get_child_segments();
+ for (int32_t segment_i = 0; segment_i < bone_segments.size(); segment_i++) {
+ Ref bone_segment = bone_segments[segment_i];
if (bone_segment.is_null()) {
continue;
}
@@ -113,7 +114,7 @@ void ManyBoneIK3DHandleGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
}
Color current_bone_color = bone_color;
for (BoneId bone_i : bones_to_process) {
- Ref ik_bone = bone_segment->get_ik_bone(bone_i);
+ Ref ik_bone = bone_segment->find_ik_bone(bone_i);
if (ik_bone.is_null()) {
continue;
}
diff --git a/modules/many_bone_ik/src/ik_bone_segment_3d.cpp b/modules/many_bone_ik/src/ik_bone_segment_3d.cpp
index d60460fa8b16..3684e12634c9 100644
--- a/modules/many_bone_ik/src/ik_bone_segment_3d.cpp
+++ b/modules/many_bone_ik/src/ik_bone_segment_3d.cpp
@@ -30,6 +30,7 @@
#include "ik_bone_segment_3d.h"
+#include "core/object/object.h"
#include "ik_effector_3d.h"
#include "ik_kusudama_3d.h"
#include "ik_limit_cone_3d.h"
@@ -37,7 +38,7 @@
#include "math/ik_node_3d.h"
#include "scene/3d/skeleton_3d.h"
-Ref IKBoneSegment3D::get_root() const {
+Ref IKBoneSegment3D::get_root() {
return root;
}
Ref IKBoneSegment3D::get_tip() const {
@@ -49,7 +50,7 @@ bool IKBoneSegment3D::is_pinned() const {
return tip->is_pinned();
}
-Vector][> IKBoneSegment3D::get_child_segments() const {
+TypedArray IKBoneSegment3D::get_child_segments() const {
return child_segments;
}
@@ -77,7 +78,12 @@ void IKBoneSegment3D::generate_default_segments_from_root(Vector][ next = Ref(memnew(IKBone3D(skeleton->get_bone_name(bone_id), skeleton, temp_tip, p_pins, p_many_bone_ik->get_default_damp(), p_many_bone_ik)));
- root_segment->bone_map[bone_id] = next;
+ Ref root_segment;
+ Ref current_segment = Ref(this);
+ while (current_segment.is_valid()) {
+ root_segment = current_segment;
+ current_segment = current_segment->get_parent_segment();
+ }
temp_tip = next;
} else {
break;
@@ -95,7 +101,8 @@ void IKBoneSegment3D::generate_default_segments_from_root(Vector][> &p_list, bool p_recursive, bool p_debug_skeleton) const {
if (p_recursive) {
for (int32_t child_i = 0; child_i < child_segments.size(); child_i++) {
- child_segments[child_i]->create_bone_list(p_list, p_recursive, p_debug_skeleton);
+ Ref segment = child_segments[child_i];
+ segment->create_bone_list(p_list, p_recursive, p_debug_skeleton);
}
}
Ref current_bone = tip;
@@ -139,8 +146,9 @@ void IKBoneSegment3D::update_pinned_list(Vector> &r_weights) {
effector_list.push_back(tip->get_pin());
}
if (passthrough_factor > 0.0) {
- for (Ref child : child_segments) {
- effector_list.append_array(child->effector_list);
+ for (int32_t segment_i = 0; segment_i < child_segments.size(); segment_i++) {
+ Ref segment = child_segments[segment_i];
+ effector_list.append_array(segment->effector_list);
}
}
}
@@ -262,7 +270,8 @@ void IKBoneSegment3D::update_tip_headings(Ref p_for_bone, PackedVector
}
void IKBoneSegment3D::segment_solver(const Vector &p_damp, float p_default_damp, bool p_constraint_mode) {
- for (Ref child : child_segments) {
+ for (int32_t segment_i = 0; segment_i < child_segments.size(); segment_i++) {
+ Ref child = child_segments[segment_i];
if (child.is_null()) {
continue;
}
@@ -295,7 +304,18 @@ void IKBoneSegment3D::qcp_solver(const Vector &p_damp, float p_default_da
void IKBoneSegment3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_pinned"), &IKBoneSegment3D::is_pinned);
- ClassDB::bind_method(D_METHOD("get_ik_bone", "bone"), &IKBoneSegment3D::get_ik_bone);
+ ClassDB::bind_method(D_METHOD("find_ik_bone", "bone"), &IKBoneSegment3D::find_ik_bone);
+ ClassDB::bind_method(D_METHOD("get_root"), &IKBoneSegment3D::get_root);
+ ClassDB::bind_method(D_METHOD("get_default_stabilizing_pass_count"), &IKBoneSegment3D::get_default_stabilizing_pass_count);
+ ClassDB::bind_method(D_METHOD("set_default_stabilizing_pass_count", "count"), &IKBoneSegment3D::set_default_stabilizing_pass_count);
+ ClassDB::bind_method(D_METHOD("set_child_segments", "segment"), &IKBoneSegment3D::set_child_segments);
+ ClassDB::bind_method(D_METHOD("get_child_segments"), &IKBoneSegment3D::get_child_segments);
+ ClassDB::bind_method(D_METHOD("set_parent_segment", "segment"), &IKBoneSegment3D::set_parent_segment);
+ ClassDB::bind_method(D_METHOD("get_parent_segment"), &IKBoneSegment3D::get_parent_segment);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "stabilizing_pass_count"), "set_default_stabilizing_pass_count", "get_default_stabilizing_pass_count");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "child_segments", PROPERTY_HINT_ARRAY_TYPE, "IKBoneSegment3D"), "set_child_segments", "get_child_segments");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "parent_segment", PROPERTY_HINT_RESOURCE_TYPE, "IKBoneSegment3D"), "set_parent_segment", "get_parent_segment");
}
Ref IKBoneSegment3D::get_parent_segment() {
@@ -304,16 +324,10 @@ Ref IKBoneSegment3D::get_parent_segment() {
IKBoneSegment3D::IKBoneSegment3D(Skeleton3D *p_skeleton, StringName p_root_bone_name, Vector][> &p_pins, ManyBoneIK3D *p_many_bone_ik, const Ref &p_parent,
BoneId p_root, BoneId p_tip) {
- root = p_root;
tip = p_tip;
skeleton = p_skeleton;
root = Ref(memnew(IKBone3D(p_root_bone_name, p_skeleton, p_parent, p_pins, Math_PI, p_many_bone_ik)));
- if (p_parent.is_valid()) {
- root_segment = p_parent->root_segment;
- } else {
- root_segment = Ref(this);
- }
- root_segment->bone_map[root->get_bone_id()] = root;
+
if (p_parent.is_valid()) {
parent_segment = p_parent;
root->set_parent(p_parent->get_tip());
@@ -332,11 +346,19 @@ Vector][> IKBoneSegment3D::get_bone_list() const {
return bones;
}
-Ref IKBoneSegment3D::get_ik_bone(BoneId p_bone) const {
- if (!bone_map.has(p_bone)) {
- return Ref();
+Ref IKBoneSegment3D::find_ik_bone(BoneId p_bone) const {
+ Ref root_segment;
+ Ref current_segment = Ref(this);
+ while (current_segment.is_valid()) {
+ root_segment = current_segment;
+ current_segment = current_segment->get_parent_segment();
+ }
+ for (Ref current_bone : root_segment->bones) {
+ if (current_bone->get_bone_id() == p_bone) {
+ return current_bone;
+ }
}
- return bone_map[p_bone];
+ return Ref();
}
void IKBoneSegment3D::create_headings_arrays() {
@@ -412,7 +434,9 @@ void IKBoneSegment3D::recursive_create_penalty_array(Ref p_bone
r_pinned_bones.push_back(current_tip);
current_falloff = pin->get_passthrough_factor();
}
- for (Ref s : p_bone_segment->get_child_segments()) {
+ TypedArray bone_segments = p_bone_segment->get_child_segments();
+ for (int32_t segment_i = 0; segment_i < bone_segments.size(); segment_i++) {
+ Ref s = bone_segments[segment_i];
recursive_create_penalty_array(s, r_penalty_array, r_pinned_bones, p_falloff * current_falloff);
}
}
@@ -420,7 +444,29 @@ void IKBoneSegment3D::recursive_create_penalty_array(Ref p_bone
void IKBoneSegment3D::recursive_create_headings_arrays_for(Ref p_bone_segment) {
p_bone_segment->create_headings_arrays();
- for (Ref segments : p_bone_segment->get_child_segments()) {
- recursive_create_headings_arrays_for(segments);
+ TypedArray segments = p_bone_segment->get_child_segments();
+ for (int32_t segment_i = 0; segment_i < segments.size(); segment_i++) {
+ Ref segment = segments[segment_i];
+ recursive_create_headings_arrays_for(segment);
}
}
+
+void IKBoneSegment3D::set_child_segments(TypedArray p_child_segments) {
+ child_segments = p_child_segments;
+}
+
+void IKBoneSegment3D::set_default_stabilizing_pass_count(int32_t p_count) {
+ default_stabilizing_pass_count = p_count;
+}
+
+int32_t IKBoneSegment3D::get_default_stabilizing_pass_count() {
+ return default_stabilizing_pass_count;
+}
+
+void IKBoneSegment3D::set_tip(Ref p_tip) {
+ tip = p_tip;
+}
+
+void IKBoneSegment3D::set_parent_segment(Ref p_parent_segment) {
+ parent_segment = p_parent_segment;
+}
diff --git a/modules/many_bone_ik/src/ik_bone_segment_3d.h b/modules/many_bone_ik/src/ik_bone_segment_3d.h
index 75bccc61a9cc..b1476b100048 100644
--- a/modules/many_bone_ik/src/ik_bone_segment_3d.h
+++ b/modules/many_bone_ik/src/ik_bone_segment_3d.h
@@ -50,9 +50,8 @@ class IKBoneSegment3D : public Resource {
Ref tip;
Vector][> bones;
Vector][> pinned_bones;
- Vector][> child_segments; // Contains only direct child chains that end with effectors or have child that end with effectors
+ TypedArray child_segments; // Contains only direct child chains that end with effectors or have child that end with effectors
Ref parent_segment;
- Ref root_segment;
Vector][> effector_list;
PackedVector3Array target_headings;
PackedVector3Array tip_headings;
@@ -72,12 +71,14 @@ class IKBoneSegment3D : public Resource {
void qcp_solver(const Vector &p_damp, float p_default_damp, bool p_translate, bool p_constraint_mode);
void update_optimal_rotation(Ref p_for_bone, real_t p_damp, bool p_translate, bool p_constraint_mode);
float get_manual_msd(const PackedVector3Array &r_htip, const PackedVector3Array &r_htarget, const Vector &p_weights);
- HashMap> bone_map;
protected:
static void _bind_methods();
public:
+ Ref get_root();
+ int32_t get_default_stabilizing_pass_count();
+ void set_default_stabilizing_pass_count(int32_t p_count);
const double evec_prec = static_cast(1E-6);
const double eval_prec = static_cast(1E-11);
static Quaternion clamp_to_quadrance_angle(Quaternion p_quat, real_t p_cos_half_angle);
@@ -85,14 +86,19 @@ class IKBoneSegment3D : public Resource {
void create_headings_arrays();
void recursive_create_penalty_array(Ref p_bone_segment, Vector> &r_penalty_array, Vector][> &r_pinned_bones, real_t p_falloff);
Ref get_parent_segment();
+ void set_parent_segment(Ref p_parent_segment);
void segment_solver(const Vector &p_damp, float p_default_damp, bool p_constraint_mode);
- Ref get_root() const;
Ref get_tip() const;
+ void set_tip(Ref p_tip);
bool is_pinned() const;
- Vector][> get_child_segments() const;
+ TypedArray get_child_segments() const;
+ void set_child_segments(TypedArray p_child_segments);
void create_bone_list(Vector][> &p_list, bool p_recursive = false, bool p_debug_skeleton = false) const;
Vector][> get_bone_list() const;
- Ref get_ik_bone(BoneId p_bone) const;
+ void set_bone_list(Vector][> p_bone_list) {
+ bones = p_bone_list;
+ }
+ Ref find_ik_bone(BoneId p_bone) const;
void generate_default_segments_from_root(Vector][> &p_pins, BoneId p_root_bone, BoneId p_tip_bone, ManyBoneIK3D *p_many_bone_ik);
void update_pinned_list(Vector> &r_weights);
IKBoneSegment3D() {}
diff --git a/modules/many_bone_ik/src/ik_effector_3d.cpp b/modules/many_bone_ik/src/ik_effector_3d.cpp
index ecf35677031d..ad5abeb2ea50 100644
--- a/modules/many_bone_ik/src/ik_effector_3d.cpp
+++ b/modules/many_bone_ik/src/ik_effector_3d.cpp
@@ -57,7 +57,7 @@ bool IKEffector3D::get_target_node_rotation() const {
return use_target_node_rotation;
}
-Ref IKEffector3D::get_ik_bone_3d() const {
+Ref IKEffector3D::find_ik_bone_3d() const {
return for_bone;
}
diff --git a/modules/many_bone_ik/src/ik_effector_3d.h b/modules/many_bone_ik/src/ik_effector_3d.h
index 7f99d9c06bec..10e4c0c5a7e8 100644
--- a/modules/many_bone_ik/src/ik_effector_3d.h
+++ b/modules/many_bone_ik/src/ik_effector_3d.h
@@ -80,7 +80,7 @@ class IKEffector3D : public Resource {
Transform3D get_target_global_transform() const;
void set_target_node_rotation(bool p_use);
bool get_target_node_rotation() const;
- Ref get_ik_bone_3d() const;
+ Ref find_ik_bone_3d() const;
bool is_following_translation_only() const;
int32_t update_effector_target_headings(PackedVector3Array *p_headings, int32_t p_index, Ref p_for_bone, const Vector *p_weights) const;
int32_t update_effector_tip_headings(PackedVector3Array *p_headings, int32_t p_index, Ref p_for_bone, bool p_is_uniform) const;
diff --git a/modules/many_bone_ik/src/many_bone_ik_3d.cpp b/modules/many_bone_ik/src/many_bone_ik_3d.cpp
index 651196e00c81..3cd1040d1db8 100644
--- a/modules/many_bone_ik/src/many_bone_ik_3d.cpp
+++ b/modules/many_bone_ik/src/many_bone_ik_3d.cpp
@@ -30,8 +30,9 @@
#include "many_bone_ik_3d.h"
#include "core/core_string_names.h"
-#include "core/error/error_macros.h"
+#include "core/variant/typed_array.h"
#include "ik_bone_3d.h"
+#include "ik_bone_segment_3d.h"
#include "ik_kusudama_3d.h"
#ifdef TOOLS_ENABLED
@@ -477,7 +478,10 @@ void ManyBoneIK3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_ui_selected_bone"), &ManyBoneIK3D::get_ui_selected_bone);
ClassDB::bind_method(D_METHOD("set_filter_bones", "bones"), &ManyBoneIK3D::set_filter_bones);
ClassDB::bind_method(D_METHOD("get_filter_bones"), &ManyBoneIK3D::get_filter_bones);
+ ClassDB::bind_method(D_METHOD("set_child_segments", "segments"), &ManyBoneIK3D::set_child_segments);
+ ClassDB::bind_method(D_METHOD("get_child_segments"), &ManyBoneIK3D::get_child_segments);
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "child_segments", PROPERTY_HINT_ARRAY_TYPE, "IKBoneSegment3D"), "set_child_segments", "get_child_segments");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton_node_path"), "set_skeleton_node_path", "get_skeleton_node_path");
ADD_PROPERTY(PropertyInfo(Variant::INT, "iterations_per_frame", PROPERTY_HINT_RANGE, "1,150,1,or_greater"), "set_iterations_per_frame", "get_iterations_per_frame");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "default_damp", PROPERTY_HINT_RANGE, "0.01,180.0,0.01,radians,exp", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_default_damp", "get_default_damp");
@@ -671,9 +675,6 @@ void ManyBoneIK3D::_set_constraint_name(int32_t p_index, String p_name) {
set_dirty();
}
-Vector][> ManyBoneIK3D::get_segmented_skeletons() {
- return segmented_skeletons;
-}
float ManyBoneIK3D::get_iterations_per_frame() const {
return iterations_per_frame;
}
@@ -743,7 +744,9 @@ void ManyBoneIK3D::execute(real_t delta) {
}
update_ik_bones_transform();
for (int32_t i = 0; i < get_iterations_per_frame(); i++) {
- for (Ref segmented_skeleton : segmented_skeletons) {
+ TypedArray segments = segmented_skeletons;
+ for (int32_t segment_i = 0; segment_i < segments.size(); segment_i++) {
+ Ref segmented_skeleton = segments[segment_i];
if (segmented_skeleton.is_null()) {
continue;
}
@@ -956,12 +959,22 @@ Vector][> ManyBoneIK3D::get_bone_list() {
void ManyBoneIK3D::set_bone_direction_transform(int32_t p_index, Transform3D p_transform) {
ERR_FAIL_INDEX(p_index, constraint_names.size());
+
+ if (!segmented_skeletons.size()) {
+ return;
+ }
+ if (!get_skeleton()) {
+ return;
+ }
String bone_name = constraint_names[p_index];
- for (Ref segmented_skeleton : segmented_skeletons) {
+
+ TypedArray segments = segmented_skeletons;
+ for (int32_t segment_i = 0; segment_i < segments.size(); segment_i++) {
+ Ref segmented_skeleton = segments[segment_i];
if (segmented_skeleton.is_null()) {
continue;
}
- Ref ik_bone = segmented_skeleton->get_ik_bone(get_skeleton()->find_bone(bone_name));
+ Ref ik_bone = segmented_skeleton->find_ik_bone(get_skeleton()->find_bone(bone_name));
if (ik_bone.is_null()) {
continue;
}
@@ -982,11 +995,13 @@ Transform3D ManyBoneIK3D::get_bone_direction_transform(int32_t p_index) const {
if (!get_skeleton()) {
return Transform3D();
}
- for (Ref segmented_skeleton : segmented_skeletons) {
+ TypedArray segments = segmented_skeletons;
+ for (int32_t segment_i = 0; segment_i < segments.size(); segment_i++) {
+ Ref segmented_skeleton = segments[segment_i];
if (segmented_skeleton.is_null()) {
continue;
}
- Ref ik_bone = segmented_skeleton->get_ik_bone(get_skeleton()->find_bone(bone_name));
+ Ref ik_bone = segmented_skeleton->find_ik_bone(get_skeleton()->find_bone(bone_name));
if (ik_bone.is_null()) {
continue;
}
@@ -1007,11 +1022,13 @@ Transform3D ManyBoneIK3D::get_constraint_orientation_transform(int32_t p_index)
if (!get_skeleton()) {
return Transform3D();
}
- for (Ref segmented_skeleton : segmented_skeletons) {
+ TypedArray segments = segmented_skeletons;
+ for (int32_t segment_i = 0; segment_i < segments.size(); segment_i++) {
+ Ref segmented_skeleton = segments[segment_i];
if (segmented_skeleton.is_null()) {
continue;
}
- Ref ik_bone = segmented_skeleton->get_ik_bone(get_skeleton()->find_bone(bone_name));
+ Ref ik_bone = segmented_skeleton->find_ik_bone(get_skeleton()->find_bone(bone_name));
if (ik_bone.is_null()) {
continue;
}
@@ -1026,14 +1043,19 @@ Transform3D ManyBoneIK3D::get_constraint_orientation_transform(int32_t p_index)
void ManyBoneIK3D::set_constraint_orientation_transform(int32_t p_index, Transform3D p_transform) {
ERR_FAIL_INDEX(p_index, constraint_names.size());
String bone_name = constraint_names[p_index];
+ if (!segmented_skeletons.size()) {
+ return;
+ }
if (!get_skeleton()) {
return;
}
- for (Ref segmented_skeleton : segmented_skeletons) {
+ TypedArray segments = segmented_skeletons;
+ for (int32_t segment_i = 0; segment_i < segments.size(); segment_i++) {
+ Ref segmented_skeleton = segments[segment_i];
if (segmented_skeleton.is_null()) {
continue;
}
- Ref ik_bone = segmented_skeleton->get_ik_bone(get_skeleton()->find_bone(bone_name));
+ Ref ik_bone = segmented_skeleton->find_ik_bone(get_skeleton()->find_bone(bone_name));
if (ik_bone.is_null()) {
continue;
}
@@ -1054,11 +1076,13 @@ Transform3D ManyBoneIK3D::get_constraint_twist_transform(int32_t p_index) const
if (!get_skeleton()) {
return Transform3D();
}
- for (Ref segmented_skeleton : segmented_skeletons) {
+ TypedArray segments = segmented_skeletons;
+ for (int32_t segment_i = 0; segment_i < segments.size(); segment_i++) {
+ Ref segmented_skeleton = segments[segment_i];
if (segmented_skeleton.is_null()) {
continue;
}
- Ref ik_bone = segmented_skeleton->get_ik_bone(get_skeleton()->find_bone(bone_name));
+ Ref ik_bone = segmented_skeleton->find_ik_bone(get_skeleton()->find_bone(bone_name));
if (ik_bone.is_null()) {
continue;
}
@@ -1073,14 +1097,20 @@ Transform3D ManyBoneIK3D::get_constraint_twist_transform(int32_t p_index) const
void ManyBoneIK3D::set_constraint_twist_transform(int32_t p_index, Transform3D p_transform) {
ERR_FAIL_INDEX(p_index, constraint_names.size());
String bone_name = constraint_names[p_index];
+
+ if (!segmented_skeletons.size()) {
+ return;
+ }
if (!get_skeleton()) {
return;
}
- for (Ref segmented_skeleton : segmented_skeletons) {
+ TypedArray segments = segmented_skeletons;
+ for (int32_t segment_i = 0; segment_i < segments.size(); segment_i++) {
+ Ref segmented_skeleton = segments[segment_i];
if (segmented_skeleton.is_null()) {
continue;
}
- Ref ik_bone = segmented_skeleton->get_ik_bone(get_skeleton()->find_bone(bone_name));
+ Ref ik_bone = segmented_skeleton->find_ik_bone(get_skeleton()->find_bone(bone_name));
if (ik_bone.is_null()) {
continue;
}
diff --git a/modules/many_bone_ik/src/many_bone_ik_3d.h b/modules/many_bone_ik/src/many_bone_ik_3d.h
index 896dea68f0cc..fd5dbc33f9ca 100644
--- a/modules/many_bone_ik/src/many_bone_ik_3d.h
+++ b/modules/many_bone_ik/src/many_bone_ik_3d.h
@@ -49,7 +49,7 @@ class ManyBoneIK3D : public Node3D {
private:
bool is_constraint_mode = false;
NodePath skeleton_path;
- Vector][> segmented_skeletons;
+ TypedArray segmented_skeletons;
int32_t constraint_count = 0;
Vector constraint_names;
int32_t pin_count = 0;
@@ -91,6 +91,13 @@ class ManyBoneIK3D : public Node3D {
void _notification(int p_what);
public:
+ void set_child_segments(TypedArray p_child_segments) {
+ segmented_skeletons = p_child_segments;
+ }
+ TypedArray get_child_segments() const {
+ return segmented_skeletons;
+ }
+
Transform3D get_godot_skeleton_transform_inverse() {
return godot_skeleton_transform_inverse;
}
@@ -111,7 +118,6 @@ class ManyBoneIK3D : public Node3D {
NodePath get_skeleton_node_path();
Skeleton3D *get_skeleton() const;
Vector][> get_bone_list();
- Vector][> get_segmented_skeletons();
float get_iterations_per_frame() const;
void set_iterations_per_frame(const float &p_iterations_per_frame);
void queue_print_skeleton();
]