Browse Source

Merge pull request #100437 from KoBeWi/ruaninstancequestionmark

Add `is_instance()` helper method to Node
Thaddeus Crews 2 months ago
parent
commit
685c7e92e5

+ 10 - 10
editor/docks/scene_tree_dock.cpp

@@ -1027,7 +1027,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
 				return;
 				return;
 			}
 			}
 
 
-			if (!node->get_scene_file_path().is_empty()) {
+			if (node->is_instance()) {
 				accept->set_text(TTR("Instantiated scenes can't become root"));
 				accept->set_text(TTR("Instantiated scenes can't become root"));
 				accept->popup_centered();
 				accept->popup_centered();
 				return;
 				return;
@@ -1111,8 +1111,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
 						Node *node = remove_list.front()->get();
 						Node *node = remove_list.front()->get();
 						if (node == editor_data->get_edited_scene_root()) {
 						if (node == editor_data->get_edited_scene_root()) {
 							msg = vformat(TTR("Delete the root node \"%s\"?"), node->get_name());
 							msg = vformat(TTR("Delete the root node \"%s\"?"), node->get_name());
-						} else if (node->get_scene_file_path().is_empty() && node->get_child_count() > 0) {
-							// Display this message only for non-instantiated scenes
+						} else if (!node->is_instance() && node->get_child_count() > 0) {
+							// Display this message only for non-instantiated scenes.
 							msg = vformat(TTR("Delete node \"%s\" and its children?"), node->get_name());
 							msg = vformat(TTR("Delete node \"%s\" and its children?"), node->get_name());
 						} else {
 						} else {
 							msg = vformat(TTR("Delete node \"%s\"?"), node->get_name());
 							msg = vformat(TTR("Delete node \"%s\"?"), node->get_name());
@@ -1169,7 +1169,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
 				break;
 				break;
 			}
 			}
 
 
-			if (tocopy != editor_data->get_edited_scene_root() && !tocopy->get_scene_file_path().is_empty()) {
+			if (tocopy != editor_data->get_edited_scene_root() && tocopy->is_instance()) {
 				accept->set_text(TTR("Can't save the branch of an already instantiated scene.\nTo create a variation of a scene, you can make an inherited scene based on the instantiated scene using Scene > New Inherited Scene... instead."));
 				accept->set_text(TTR("Can't save the branch of an already instantiated scene.\nTo create a variation of a scene, you can make an inherited scene based on the instantiated scene using Scene > New Inherited Scene... instead."));
 				accept->popup_centered();
 				accept->popup_centered();
 				break;
 				break;
@@ -1281,7 +1281,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
 			if (e) {
 			if (e) {
 				Node *node = e->get();
 				Node *node = e->get();
 				if (node) {
 				if (node) {
-					bool is_external = (!node->get_scene_file_path().is_empty());
+					bool is_external = node->is_instance();
 					bool is_top_level = node->get_owner() == nullptr;
 					bool is_top_level = node->get_owner() == nullptr;
 					if (!is_external || is_top_level) {
 					if (!is_external || is_top_level) {
 						break;
 						break;
@@ -1353,7 +1353,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
 						break;
 						break;
 					}
 					}
 
 
-					ERR_FAIL_COND(node->get_scene_file_path().is_empty());
+					ERR_FAIL_COND(!node->is_instance());
 					undo_redo->create_action(TTR("Make Local"));
 					undo_redo->create_action(TTR("Make Local"));
 					undo_redo->add_do_method(node, "set_scene_file_path", "");
 					undo_redo->add_do_method(node, "set_scene_file_path", "");
 					undo_redo->add_undo_method(node, "set_scene_file_path", node->get_scene_file_path());
 					undo_redo->add_undo_method(node, "set_scene_file_path", node->get_scene_file_path());
@@ -2327,7 +2327,7 @@ bool SceneTreeDock::_validate_no_instance() {
 	const List<Node *> &selection = editor_selection->get_top_selected_node_list();
 	const List<Node *> &selection = editor_selection->get_top_selected_node_list();
 
 
 	for (Node *E : selection) {
 	for (Node *E : selection) {
-		if (E != edited_scene && !E->get_scene_file_path().is_empty()) {
+		if (E != edited_scene && E->is_instance()) {
 			accept->set_text(TTR("This operation can't be done on instantiated scenes."));
 			accept->set_text(TTR("This operation can't be done on instantiated scenes."));
 			accept->popup_centered();
 			accept->popup_centered();
 			return false;
 			return false;
@@ -3894,7 +3894,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
 
 
 		bool can_replace = true;
 		bool can_replace = true;
 		for (Node *E : selection) {
 		for (Node *E : selection) {
-			if (E != edited_scene && (E->get_owner() != edited_scene || !E->get_scene_file_path().is_empty())) {
+			if (E != edited_scene && (E->get_owner() != edited_scene || E->is_instance())) {
 				can_replace = false;
 				can_replace = false;
 				break;
 				break;
 			}
 			}
@@ -3957,7 +3957,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
 	}
 	}
 
 
 	if (selection.size() == 1) {
 	if (selection.size() == 1) {
-		bool is_external = (!selection.front()->get()->get_scene_file_path().is_empty());
+		bool is_external = selection.front()->get()->is_instance();
 		if (is_external) {
 		if (is_external) {
 			bool is_inherited = selection.front()->get()->get_scene_inherited_state().is_valid();
 			bool is_inherited = selection.front()->get()->get_scene_inherited_state().is_valid();
 			bool is_top_level = selection.front()->get()->get_owner() == nullptr;
 			bool is_top_level = selection.front()->get()->get_owner() == nullptr;
@@ -3994,7 +3994,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
 	}
 	}
 	menu->add_separator();
 	menu->add_separator();
 
 
-	if (full_selection.size() == 1 && !selection.front()->get()->get_scene_file_path().is_empty()) {
+	if (full_selection.size() == 1 && selection.front()->get()->is_instance()) {
 		menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ShowInFileSystem")), ED_GET_SHORTCUT("scene_tree/show_in_file_system"), TOOL_SHOW_IN_FILE_SYSTEM);
 		menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ShowInFileSystem")), ED_GET_SHORTCUT("scene_tree/show_in_file_system"), TOOL_SHOW_IN_FILE_SYSTEM);
 	}
 	}
 
 

+ 3 - 3
editor/editor_data.cpp

@@ -668,7 +668,7 @@ bool EditorData::_find_updated_instances(Node *p_root, Node *p_node, HashSet<Str
 
 
 	if (p_node == p_root) {
 	if (p_node == p_root) {
 		ss = p_node->get_scene_inherited_state();
 		ss = p_node->get_scene_inherited_state();
-	} else if (!p_node->get_scene_file_path().is_empty()) {
+	} else if (p_node->is_instance()) {
 		ss = p_node->get_scene_instance_state();
 		ss = p_node->get_scene_instance_state();
 	}
 	}
 
 
@@ -773,7 +773,7 @@ void EditorData::set_edited_scene_root(Node *p_root) {
 	ERR_FAIL_INDEX(current_edited_scene, edited_scene.size());
 	ERR_FAIL_INDEX(current_edited_scene, edited_scene.size());
 	edited_scene.write[current_edited_scene].root = p_root;
 	edited_scene.write[current_edited_scene].root = p_root;
 	if (p_root) {
 	if (p_root) {
-		if (!p_root->get_scene_file_path().is_empty()) {
+		if (p_root->is_instance()) {
 			edited_scene.write[current_edited_scene].path = p_root->get_scene_file_path();
 			edited_scene.write[current_edited_scene].path = p_root->get_scene_file_path();
 		} else {
 		} else {
 			p_root->set_scene_file_path(edited_scene[current_edited_scene].path);
 			p_root->set_scene_file_path(edited_scene[current_edited_scene].path);
@@ -839,7 +839,7 @@ Ref<Script> EditorData::get_scene_root_script(int p_idx) const {
 	Ref<Script> s = edited_scene[p_idx].root->get_script();
 	Ref<Script> s = edited_scene[p_idx].root->get_script();
 	if (s.is_null() && edited_scene[p_idx].root->get_child_count()) {
 	if (s.is_null() && edited_scene[p_idx].root->get_child_count()) {
 		Node *n = edited_scene[p_idx].root->get_child(0);
 		Node *n = edited_scene[p_idx].root->get_child(0);
-		while (s.is_null() && n && n->get_scene_file_path().is_empty()) {
+		while (s.is_null() && n && !n->is_instance()) {
 			s = n->get_script();
 			s = n->get_script();
 			n = n->get_parent();
 			n = n->get_parent();
 		}
 		}

+ 1 - 1
editor/scene/canvas_item_editor_plugin.cpp

@@ -1610,7 +1610,7 @@ bool CanvasItemEditor::_gui_input_open_scene_on_double_click(const Ref<InputEven
 		List<CanvasItem *> selection = _get_edited_canvas_items();
 		List<CanvasItem *> selection = _get_edited_canvas_items();
 		if (selection.size() == 1) {
 		if (selection.size() == 1) {
 			CanvasItem *ci = selection.front()->get();
 			CanvasItem *ci = selection.front()->get();
-			if (!ci->get_scene_file_path().is_empty() && ci != EditorNode::get_singleton()->get_edited_scene()) {
+			if (ci->is_instance() && ci != EditorNode::get_singleton()->get_edited_scene()) {
 				EditorNode::get_singleton()->load_scene(ci->get_scene_file_path());
 				EditorNode::get_singleton()->load_scene(ci->get_scene_file_path());
 				return true;
 				return true;
 			}
 			}

+ 3 - 3
editor/scene/scene_tree_editor.cpp

@@ -670,7 +670,7 @@ void SceneTreeEditor::_update_node_tooltip(Node *p_node, TreeItem *p_item) {
 			p_item->add_button(0, get_editor_theme_icon(SNAME("InstanceOptions")), BUTTON_SUBSCENE, false, TTR("Open in Editor"));
 			p_item->add_button(0, get_editor_theme_icon(SNAME("InstanceOptions")), BUTTON_SUBSCENE, false, TTR("Open in Editor"));
 		}
 		}
 		tooltip += String("\n" + TTR("Inherits:") + " " + p_node->get_scene_inherited_state()->get_path());
 		tooltip += String("\n" + TTR("Inherits:") + " " + p_node->get_scene_inherited_state()->get_path());
-	} else if (p_node != get_scene_node() && !p_node->get_scene_file_path().is_empty() && can_open_instance) {
+	} else if (p_node != get_scene_node() && p_node->is_instance() && can_open_instance) {
 		if (p_item->get_button_by_id(0, BUTTON_SUBSCENE) == -1) {
 		if (p_item->get_button_by_id(0, BUTTON_SUBSCENE) == -1) {
 			p_item->add_button(0, get_editor_theme_icon(SNAME("InstanceOptions")), BUTTON_SUBSCENE, false, TTR("Open in Editor"));
 			p_item->add_button(0, get_editor_theme_icon(SNAME("InstanceOptions")), BUTTON_SUBSCENE, false, TTR("Open in Editor"));
 		}
 		}
@@ -1532,7 +1532,7 @@ void SceneTreeEditor::rename_node(Node *p_node, const String &p_name, TreeItem *
 	// Trim leading/trailing whitespace to prevent node names from containing accidental whitespace,
 	// Trim leading/trailing whitespace to prevent node names from containing accidental whitespace,
 	// which would make it more difficult to get the node via `get_node()`.
 	// which would make it more difficult to get the node via `get_node()`.
 	new_name = new_name.strip_edges();
 	new_name = new_name.strip_edges();
-	if (new_name.is_empty() && p_node->get_owner() != nullptr && !p_node->get_scene_file_path().is_empty()) {
+	if (new_name.is_empty() && p_node->get_owner() != nullptr && p_node->is_instance()) {
 		// If name is empty and node is root of an instance, revert to the original name.
 		// If name is empty and node is root of an instance, revert to the original name.
 		const Ref<PackedScene> node_scene = ResourceLoader::load(p_node->get_scene_file_path());
 		const Ref<PackedScene> node_scene = ResourceLoader::load(p_node->get_scene_file_path());
 		if (node_scene.is_valid()) {
 		if (node_scene.is_valid()) {
@@ -1966,7 +1966,7 @@ bool SceneTreeEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_d
 		for (int i = 0; i < nodes.size(); i++) {
 		for (int i = 0; i < nodes.size(); i++) {
 			Node *n = get_node(nodes[i]);
 			Node *n = get_node(nodes[i]);
 			// Nodes from an instantiated scene can't be rearranged.
 			// Nodes from an instantiated scene can't be rearranged.
-			if (n && n->get_owner() && n->get_owner() != get_scene_node() && !n->get_owner()->get_scene_file_path().is_empty()) {
+			if (n && n->get_owner() && n->get_owner() != get_scene_node() && n->get_owner()->is_instance()) {
 				return false;
 				return false;
 			}
 			}
 		}
 		}

+ 3 - 3
scene/main/node.cpp

@@ -2797,7 +2797,7 @@ Node *Node::_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap) c
 		nip->set_instance_path(ip->get_instance_path());
 		nip->set_instance_path(ip->get_instance_path());
 		node = nip;
 		node = nip;
 
 
-	} else if ((p_flags & DUPLICATE_USE_INSTANTIATION) && !get_scene_file_path().is_empty()) {
+	} else if ((p_flags & DUPLICATE_USE_INSTANTIATION) && is_instance()) {
 		Ref<PackedScene> res = ResourceLoader::load(get_scene_file_path());
 		Ref<PackedScene> res = ResourceLoader::load(get_scene_file_path());
 		ERR_FAIL_COND_V(res.is_null(), nullptr);
 		ERR_FAIL_COND_V(res.is_null(), nullptr);
 		PackedScene::GenEditState edit_state = PackedScene::GEN_EDIT_STATE_DISABLED;
 		PackedScene::GenEditState edit_state = PackedScene::GEN_EDIT_STATE_DISABLED;
@@ -2822,7 +2822,7 @@ Node *Node::_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap) c
 		ERR_FAIL_NULL_V(node, nullptr);
 		ERR_FAIL_NULL_V(node, nullptr);
 	}
 	}
 
 
-	if (!get_scene_file_path().is_empty()) { //an instance
+	if (is_instance()) {
 		node->set_scene_file_path(get_scene_file_path());
 		node->set_scene_file_path(get_scene_file_path());
 		node->data.editable_instance = data.editable_instance;
 		node->data.editable_instance = data.editable_instance;
 	}
 	}
@@ -2853,7 +2853,7 @@ Node *Node::_duplicate(int p_flags, HashMap<const Node *, Node *> *r_duplimap) c
 
 
 				node_tree.push_back(descendant);
 				node_tree.push_back(descendant);
 
 
-				if (!descendant->get_scene_file_path().is_empty() && instance_roots.has(descendant->get_owner())) {
+				if (descendant->is_instance() && instance_roots.has(descendant->get_owner())) {
 					instance_roots.push_back(descendant);
 					instance_roots.push_back(descendant);
 				}
 				}
 			}
 			}

+ 4 - 0
scene/main/node.h

@@ -821,6 +821,10 @@ public:
 	void set_thread_safe(const StringName &p_property, const Variant &p_value);
 	void set_thread_safe(const StringName &p_property, const Variant &p_value);
 	void notify_thread_safe(int p_notification);
 	void notify_thread_safe(int p_notification);
 
 
+	/* HELPER */
+
+	bool is_instance() const { return !data.scene_file_path.is_empty(); }
+
 	// These inherited functions need proper multithread locking when overridden in Node.
 	// These inherited functions need proper multithread locking when overridden in Node.
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 
 

+ 1 - 1
scene/property_utils.cpp

@@ -258,7 +258,7 @@ Vector<SceneState::PackState> PropertyUtils::get_node_states_stack(const Node *p
 					}
 					}
 				}
 				}
 				break;
 				break;
-			} else if (!n->get_scene_file_path().is_empty()) {
+			} else if (n->is_instance()) {
 				const Ref<SceneState> &state = n->get_scene_instance_state();
 				const Ref<SceneState> &state = n->get_scene_instance_state();
 				_collect_inheritance_chain(state, n->get_path_to(p_node), states_stack);
 				_collect_inheritance_chain(state, n->get_path_to(p_node), states_stack);
 			}
 			}

+ 4 - 5
scene/resources/packed_scene.cpp

@@ -749,7 +749,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
 
 
 	// save the child instantiated scenes that are chosen as editable, so they can be restored
 	// save the child instantiated scenes that are chosen as editable, so they can be restored
 	// upon load back
 	// upon load back
-	if (p_node != p_owner && !p_node->get_scene_file_path().is_empty() && p_owner->is_editable_instance(p_node)) {
+	if (p_node != p_owner && p_node->is_instance() && p_owner->is_editable_instance(p_node)) {
 		editable_instances.push_back(p_owner->get_path_to(p_node));
 		editable_instances.push_back(p_owner->get_path_to(p_node));
 		// Node is the root of an editable instance.
 		// Node is the root of an editable instance.
 		is_editable_instance = true;
 		is_editable_instance = true;
@@ -783,7 +783,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Has
 	bool instantiated_by_owner = false;
 	bool instantiated_by_owner = false;
 	Vector<SceneState::PackState> states_stack = PropertyUtils::get_node_states_stack(p_node, p_owner, &instantiated_by_owner);
 	Vector<SceneState::PackState> states_stack = PropertyUtils::get_node_states_stack(p_node, p_owner, &instantiated_by_owner);
 
 
-	if (!p_node->get_scene_file_path().is_empty() && p_node->get_owner() == p_owner && instantiated_by_owner) {
+	if (p_node->is_instance() && p_node->get_owner() == p_owner && instantiated_by_owner) {
 		if (p_node->get_scene_instance_load_placeholder()) {
 		if (p_node->get_scene_instance_load_placeholder()) {
 			//it's a placeholder, use the placeholder path
 			//it's a placeholder, use the placeholder path
 			nd.instance = _vm_get_variant(p_node->get_scene_file_path(), variant_map);
 			nd.instance = _vm_get_variant(p_node->get_scene_file_path(), variant_map);
@@ -1123,7 +1123,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, HashMap<String
 
 
 			ERR_CONTINUE(!common_parent);
 			ERR_CONTINUE(!common_parent);
 
 
-			if (common_parent != p_owner && common_parent->get_scene_file_path().is_empty()) {
+			if (common_parent != p_owner && !common_parent->is_instance()) {
 				common_parent = common_parent->get_owner();
 				common_parent = common_parent->get_owner();
 			}
 			}
 
 
@@ -1183,8 +1183,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, HashMap<String
 
 
 						nl = nullptr;
 						nl = nullptr;
 					} else {
 					} else {
-						if (!nl->get_scene_file_path().is_empty()) {
-							//is an instance
+						if (nl->is_instance()) {
 							Ref<SceneState> state = nl->get_scene_instance_state();
 							Ref<SceneState> state = nl->get_scene_instance_state();
 							if (state.is_valid()) {
 							if (state.is_valid()) {
 								int from_node = state->find_node_by_path(nl->get_path_to(p_node));
 								int from_node = state->find_node_by_path(nl->get_path_to(p_node));