Add is_instance() helper method to Node

This commit is contained in:
kobewi 2024-12-15 17:01:30 +01:00
parent 4d1f26e1fd
commit 11adf408ab
8 changed files with 29 additions and 26 deletions

View file

@ -1024,7 +1024,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;
@ -1108,8 +1108,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) { } else if (!node->is_instance() && node->get_child_count() > 0) {
// Display this message only for non-instantiated scenes // 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());
@ -1166,7 +1166,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;
@ -1278,7 +1278,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;
@ -1350,7 +1350,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());
@ -2319,7 +2319,7 @@ bool SceneTreeDock::_validate_no_instance() {
List<Node *> selection = editor_selection->get_top_selected_node_list(); 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;
@ -3856,7 +3856,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;
} }
@ -3919,7 +3919,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;
@ -3956,7 +3956,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);
} }

View file

@ -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();
} }

View file

@ -1607,7 +1607,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;
} }

View file

@ -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"));
} }
@ -1521,7 +1521,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()) {
@ -1955,7 +1955,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;
} }
} }

View file

@ -2772,7 +2772,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;
@ -2797,7 +2797,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;
} }
@ -2828,7 +2828,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);
} }
} }

View file

@ -818,6 +818,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

View file

@ -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);
} }

View file

@ -732,7 +732,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;
@ -766,7 +766,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);
@ -1106,7 +1106,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();
} }
@ -1166,8 +1166,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()) { if (nl->is_instance()) {
//is an 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));