diff --git a/doc/classes/Skeleton3D.xml b/doc/classes/Skeleton3D.xml index 610550d8bda..1167b70c8d2 100644 --- a/doc/classes/Skeleton3D.xml +++ b/doc/classes/Skeleton3D.xml @@ -155,6 +155,13 @@ Returns the rest transform for a bone [param bone_idx]. + + + + Returns all bone names concatenated with commas ([code],[/code]) as a single [StringName]. + It is useful to set it as a hint for the enum property. + + diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp index 27167386843..6aade24e4e0 100644 --- a/scene/3d/bone_attachment_3d.cpp +++ b/scene/3d/bone_attachment_3d.cpp @@ -44,16 +44,8 @@ void BoneAttachment3D::_validate_property(PropertyInfo &p_property) const { } if (parent) { - String names; - for (int i = 0; i < parent->get_bone_count(); i++) { - if (i > 0) { - names += ","; - } - names += parent->get_bone_name(i); - } - p_property.hint = PROPERTY_HINT_ENUM; - p_property.hint_string = names; + p_property.hint_string = parent->get_concatenated_bone_names(); } else { p_property.hint = PROPERTY_HINT_NONE; p_property.hint_string = ""; diff --git a/scene/3d/physics/physical_bone_3d.cpp b/scene/3d/physics/physical_bone_3d.cpp index c6be2a9da8d..c290f16c0d9 100644 --- a/scene/3d/physics/physical_bone_3d.cpp +++ b/scene/3d/physics/physical_bone_3d.cpp @@ -738,15 +738,7 @@ bool PhysicalBone3D::_get(const StringName &p_name, Variant &r_ret) const { void PhysicalBone3D::_get_property_list(List *p_list) const { Skeleton3D *skeleton = get_skeleton(); if (skeleton) { - String names; - for (int i = 0; i < skeleton->get_bone_count(); i++) { - if (i > 0) { - names += ","; - } - names += skeleton->get_bone_name(i); - } - - p_list->push_back(PropertyInfo(Variant::STRING_NAME, PNAME("bone_name"), PROPERTY_HINT_ENUM, names)); + p_list->push_back(PropertyInfo(Variant::STRING_NAME, PNAME("bone_name"), PROPERTY_HINT_ENUM, skeleton->get_concatenated_bone_names())); } else { p_list->push_back(PropertyInfo(Variant::STRING_NAME, PNAME("bone_name"))); } diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index a4804e928a5..21e82adf47a 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -265,11 +265,31 @@ void Skeleton3D::_update_process_order() { bones_backup.resize(bones.size()); + concatenated_bone_names = StringName(); + process_order_dirty = false; emit_signal("bone_list_changed"); } +void Skeleton3D::_update_bone_names() const { + String names; + for (int i = 0; i < bones.size(); i++) { + if (i > 0) { + names += ","; + } + names += bones[i].name; + } + concatenated_bone_names = StringName(names); +} + +StringName Skeleton3D::get_concatenated_bone_names() const { + if (concatenated_bone_names == StringName()) { + _update_bone_names(); + } + return concatenated_bone_names; +} + #ifndef DISABLE_DEPRECATED void Skeleton3D::setup_simulator() { if (simulator && simulator->get_parent() == this) { @@ -983,6 +1003,8 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone_name", "bone_idx"), &Skeleton3D::get_bone_name); ClassDB::bind_method(D_METHOD("set_bone_name", "bone_idx", "name"), &Skeleton3D::set_bone_name); + ClassDB::bind_method(D_METHOD("get_concatenated_bone_names"), &Skeleton3D::get_concatenated_bone_names); + ClassDB::bind_method(D_METHOD("get_bone_parent", "bone_idx"), &Skeleton3D::get_bone_parent); ClassDB::bind_method(D_METHOD("set_bone_parent", "bone_idx", "parent_idx"), &Skeleton3D::set_bone_parent); diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index 23b94239936..b8e38242b9d 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -150,6 +150,9 @@ private: Vector parentless_bones; HashMap name_to_bone_index; + mutable StringName concatenated_bone_names = StringName(); + void _update_bone_names() const; + void _make_dirty(); bool dirty = false; bool rest_dirty = false; @@ -200,6 +203,7 @@ public: int find_bone(const String &p_name) const; String get_bone_name(int p_bone) const; void set_bone_name(int p_bone, const String &p_name); + StringName get_concatenated_bone_names() const; bool is_bone_parent_of(int p_bone_id, int p_parent_bone_id) const; diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp index 78a21ba9e1c..0d6316ee358 100644 --- a/scene/3d/skeleton_ik_3d.cpp +++ b/scene/3d/skeleton_ik_3d.cpp @@ -306,16 +306,8 @@ void SkeletonIK3D::_validate_property(PropertyInfo &p_property) const { if (p_property.name == "root_bone" || p_property.name == "tip_bone") { Skeleton3D *skeleton = get_skeleton(); if (skeleton) { - String names("--,"); - for (int i = 0; i < skeleton->get_bone_count(); i++) { - if (i > 0) { - names += ","; - } - names += skeleton->get_bone_name(i); - } - p_property.hint = PROPERTY_HINT_ENUM; - p_property.hint_string = names; + p_property.hint_string = skeleton->get_concatenated_bone_names(); } else { p_property.hint = PROPERTY_HINT_NONE; p_property.hint_string = "";