Browse Source

added list_orphan_nodes, edited print_orphan_nodes

print_orphan_nodes now prints the script file attached to the node.
list_orphan_nodes was created to return the same data as print_orphan_nodes in a dictionary format for users who wish to process this data differently than the print_orphan_nodes behavior.
Haunted Bees 1 year ago
parent
commit
0ccdcb4a16
3 changed files with 36 additions and 1 deletions
  1. 7 0
      doc/classes/Node.xml
  2. 28 1
      scene/main/node.cpp
  3. 1 0
      scene/main/node.h

+ 7 - 0
doc/classes/Node.xml

@@ -495,6 +495,13 @@
 				Fetches a node by [NodePath]. Similar to [method get_node], but does not generate an error if [param path] does not point to a valid node.
 				Fetches a node by [NodePath]. Similar to [method get_node], but does not generate an error if [param path] does not point to a valid node.
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="get_orphan_node_ids" qualifiers="static">
+			<return type="int[]" />
+			<description>
+				Returns object IDs of all orphan nodes (nodes outside the [SceneTree]). Used for debugging.
+				[b]Note:[/b] [method get_orphan_node_ids] only works in debug builds. When called in a project exported in release mode, [method get_orphan_node_ids] will return an empty array.
+			</description>
+		</method>
 		<method name="get_parent" qualifiers="const">
 		<method name="get_parent" qualifiers="const">
 			<return type="Node" />
 			<return type="Node" />
 			<description>
 			<description>

+ 28 - 1
scene/main/node.cpp

@@ -3482,9 +3482,17 @@ static void _print_orphan_nodes_routine(Object *p_obj) {
 		path = String(p->get_name()) + "/" + p->get_path_to(n);
 		path = String(p->get_name()) + "/" + p->get_path_to(n);
 	}
 	}
 
 
+	String source;
+	Variant script = n->get_script();
+	if (!script.is_null()) {
+		Resource *obj = Object::cast_to<Resource>(script);
+		source = obj->get_path();
+	}
+
 	List<String> info_strings;
 	List<String> info_strings;
 	info_strings.push_back(path);
 	info_strings.push_back(path);
 	info_strings.push_back(n->get_class());
 	info_strings.push_back(n->get_class());
+	info_strings.push_back(source);
 
 
 	_print_orphan_nodes_map[p_obj->get_instance_id()] = info_strings;
 	_print_orphan_nodes_map[p_obj->get_instance_id()] = info_strings;
 }
 }
@@ -3499,12 +3507,30 @@ void Node::print_orphan_nodes() {
 	ObjectDB::debug_objects(_print_orphan_nodes_routine);
 	ObjectDB::debug_objects(_print_orphan_nodes_routine);
 
 
 	for (const KeyValue<ObjectID, List<String>> &E : _print_orphan_nodes_map) {
 	for (const KeyValue<ObjectID, List<String>> &E : _print_orphan_nodes_map) {
-		print_line(itos(E.key) + " - Stray Node: " + E.value.get(0) + " (Type: " + E.value.get(1) + ")");
+		print_line(itos(E.key) + " - Stray Node: " + E.value.get(0) + " (Type: " + E.value.get(1) + ") (Source:" + E.value.get(2) + ")");
+	}
+
+	// Flush it after use.
+	_print_orphan_nodes_map.clear();
+#endif
+}
+TypedArray<int> Node::get_orphan_node_ids() {
+	TypedArray<int> ret;
+#ifdef DEBUG_ENABLED
+	// Make sure it's empty.
+	_print_orphan_nodes_map.clear();
+
+	// Collect and return information about orphan nodes.
+	ObjectDB::debug_objects(_print_orphan_nodes_routine);
+
+	for (const KeyValue<ObjectID, List<String>> &E : _print_orphan_nodes_map) {
+		ret.push_back(E.key);
 	}
 	}
 
 
 	// Flush it after use.
 	// Flush it after use.
 	_print_orphan_nodes_map.clear();
 	_print_orphan_nodes_map.clear();
 #endif
 #endif
+	return ret;
 }
 }
 
 
 void Node::queue_free() {
 void Node::queue_free() {
@@ -3815,6 +3841,7 @@ void Node::_bind_methods() {
 	GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/node_name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case,kebab-case"), NAME_CASING_PASCAL_CASE);
 	GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/node_name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case,kebab-case"), NAME_CASING_PASCAL_CASE);
 
 
 	ClassDB::bind_static_method("Node", D_METHOD("print_orphan_nodes"), &Node::print_orphan_nodes);
 	ClassDB::bind_static_method("Node", D_METHOD("print_orphan_nodes"), &Node::print_orphan_nodes);
+	ClassDB::bind_static_method("Node", D_METHOD("get_orphan_node_ids"), &Node::get_orphan_node_ids);
 	ClassDB::bind_method(D_METHOD("add_sibling", "sibling", "force_readable_name"), &Node::add_sibling, DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("add_sibling", "sibling", "force_readable_name"), &Node::add_sibling, DEFVAL(false));
 
 
 	ClassDB::bind_method(D_METHOD("set_name", "name"), &Node::set_name);
 	ClassDB::bind_method(D_METHOD("set_name", "name"), &Node::set_name);

+ 1 - 0
scene/main/node.h

@@ -742,6 +742,7 @@ public:
 	ProcessThreadGroup get_process_thread_group() const;
 	ProcessThreadGroup get_process_thread_group() const;
 
 
 	static void print_orphan_nodes();
 	static void print_orphan_nodes();
+	static TypedArray<int> get_orphan_node_ids();
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 	String validate_child_name(Node *p_child);
 	String validate_child_name(Node *p_child);