Browse Source

Merge pull request #92925 from TokageItLab/concatenated-bone-names

Add `get_concatenated_bone_names()` to `Skeleton3D` for `SkeletonModifier3D`'s enum hints
Rémi Verschelde 1 year ago
parent
commit
821338c0d1

+ 7 - 0
doc/classes/Skeleton3D.xml

@@ -155,6 +155,13 @@
 				Returns the rest transform for a bone [param bone_idx].
 			</description>
 		</method>
+		<method name="get_concatenated_bone_names" qualifiers="const">
+			<return type="StringName" />
+			<description>
+				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.
+			</description>
+		</method>
 		<method name="get_parentless_bones" qualifiers="const">
 			<return type="PackedInt32Array" />
 			<description>

+ 1 - 9
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 = "";

+ 1 - 9
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<PropertyInfo> *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")));
 	}

+ 22 - 0
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);
 

+ 4 - 0
scene/3d/skeleton_3d.h

@@ -150,6 +150,9 @@ private:
 	Vector<int> parentless_bones;
 	HashMap<String, int> 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;
 

+ 1 - 9
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 = "";