diff --git a/editor/docks/scene_tree_dock.cpp b/editor/docks/scene_tree_dock.cpp index e592a32d2fa..364492390a2 100644 --- a/editor/docks/scene_tree_dock.cpp +++ b/editor/docks/scene_tree_dock.cpp @@ -1073,8 +1073,11 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { break; } Ref mne = memnew(MultiNodeEdit); - for (const KeyValue &E : editor_selection->get_selection()) { - mne->add_node(root->get_path_to(E.key)); + for (const KeyValue &E : editor_selection->get_selection()) { + Node *node = ObjectDB::get_instance(E.key); + if (node) { + mne->add_node(root->get_path_to(node)); + } } _push_item(mne.ptr()); @@ -2930,7 +2933,10 @@ void SceneTreeDock::_selection_changed() { //automatically turn on multi-edit _tool_selected(TOOL_MULTI_EDIT); } else if (selection_size == 1) { - _handle_select(editor_selection->get_selection().begin()->key); + Node *node = ObjectDB::get_instance(editor_selection->get_selection().begin()->key); + if (node) { + _handle_select(node); + } } else if (selection_size == 0) { _push_item(nullptr); } @@ -2940,10 +2946,12 @@ void SceneTreeDock::_selection_changed() { // Track script changes in newly selected nodes. node_previous_selection.reserve(editor_selection->get_selection().size()); - for (const KeyValue &E : editor_selection->get_selection()) { - Node *node = E.key; - node_previous_selection.push_back(node->get_instance_id()); - node->connect(CoreStringName(script_changed), callable_mp(this, &SceneTreeDock::_queue_update_script_button)); + for (const KeyValue &E : editor_selection->get_selection()) { + Node *node = ObjectDB::get_instance(E.key); + if (node) { + node_previous_selection.push_back(E.key); + node->connect(CoreStringName(script_changed), callable_mp(this, &SceneTreeDock::_queue_update_script_button)); + } } _queue_update_script_button(); } @@ -3369,12 +3377,12 @@ void SceneTreeDock::set_edited_scene(Node *p_scene) { edited_scene = p_scene; } -static bool _is_same_selection(const Vector &p_first, const HashMap &p_second) { +static bool _is_same_selection(const Vector &p_first, const HashMap &p_second) { if (p_first.size() != p_second.size()) { return false; } for (Node *node : p_first) { - if (!p_second.has(node)) { + if (!p_second.has(node->get_instance_id())) { return false; } } diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 02375f0c194..f84e1685f6c 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -1214,15 +1214,15 @@ EditorData::~EditorData() { /////////////////////////////////////////////////////////////////////////////// void EditorSelection::_node_removed(Node *p_node) { - if (!selection.has(p_node)) { + ERR_FAIL_NULL(p_node); + ObjectID nid = p_node->get_instance_id(); + if (!selection.has(nid)) { return; } - Object *meta = selection[p_node]; - if (meta) { - memdelete(meta); - } - selection.erase(p_node); + Object *meta = selection[nid]; + memdelete_notnull(meta); + selection.erase(nid); changed = true; node_list_changed = true; } @@ -1230,7 +1230,8 @@ void EditorSelection::_node_removed(Node *p_node) { void EditorSelection::add_node(Node *p_node) { ERR_FAIL_NULL(p_node); ERR_FAIL_COND(!p_node->is_inside_tree()); - if (selection.has(p_node)) { + ObjectID nid = p_node->get_instance_id(); + if (selection.has(nid)) { return; } @@ -1243,30 +1244,32 @@ void EditorSelection::add_node(Node *p_node) { break; } } - selection[p_node] = meta; + selection[nid] = meta; p_node->connect(SceneStringName(tree_exiting), callable_mp(this, &EditorSelection::_node_removed).bind(p_node), CONNECT_ONE_SHOT); } void EditorSelection::remove_node(Node *p_node) { ERR_FAIL_NULL(p_node); - if (!selection.has(p_node)) { + ObjectID nid = p_node->get_instance_id(); + if (!selection.has(nid)) { return; } changed = true; node_list_changed = true; - Object *meta = selection[p_node]; - if (meta) { - memdelete(meta); - } - selection.erase(p_node); + Object *meta = selection[nid]; + memdelete_notnull(meta); + selection.erase(nid); p_node->disconnect(SceneStringName(tree_exiting), callable_mp(this, &EditorSelection::_node_removed)); } bool EditorSelection::is_selected(Node *p_node) const { - return selection.has(p_node); + if (!p_node) { + return false; + } + return selection.has(p_node->get_instance_id()); } void EditorSelection::_bind_methods() { @@ -1295,12 +1298,15 @@ void EditorSelection::_update_node_list() { // If the selection does not have the parent of the selected node, then add the node to the node list. // However, if the parent is already selected, then adding this node is redundant as // it is included with the parent, so skip it. - for (const KeyValue &E : selection) { - Node *parent = E.key; + for (const KeyValue &E : selection) { + Node *parent = ObjectDB::get_instance(E.key); + if (!parent) { + continue; + } parent = parent->get_parent(); bool skip = false; while (parent) { - if (selection.has(parent)) { + if (selection.has(parent->get_instance_id())) { skip = true; break; } @@ -1337,8 +1343,11 @@ void EditorSelection::_emit_change() { TypedArray EditorSelection::get_top_selected_nodes() { TypedArray ret; - for (const Node *E : top_selected_node_list) { - ret.push_back(E); + for (const ObjectID &nid : top_selected_node_list) { + Node *node = ObjectDB::get_instance(nid); + if (node) { + ret.push_back(node); + } } return ret; @@ -1347,26 +1356,39 @@ TypedArray EditorSelection::get_top_selected_nodes() { TypedArray EditorSelection::get_selected_nodes() { TypedArray ret; - for (const KeyValue &E : selection) { - ret.push_back(E.key); + for (const KeyValue &E : selection) { + Node *node = ObjectDB::get_instance(E.key); + if (node) { + ret.push_back(node); + } } return ret; } -const List &EditorSelection::get_top_selected_node_list() { +List EditorSelection::get_top_selected_node_list() { if (changed) { update(); } else { _update_node_list(); } - return top_selected_node_list; + List node_list; + for (const ObjectID &nid : top_selected_node_list) { + Node *node = ObjectDB::get_instance(nid); + if (node) { + node_list.push_back(node); + } + } + return node_list; } List EditorSelection::get_full_selected_node_list() { List node_list; - for (const KeyValue &E : selection) { - node_list.push_back(E.key); + for (const KeyValue &E : selection) { + Node *node = ObjectDB::get_instance(E.key); + if (node) { + node_list.push_back(node); + } } return node_list; @@ -1374,7 +1396,10 @@ List EditorSelection::get_full_selected_node_list() { void EditorSelection::clear() { while (!selection.is_empty()) { - remove_node(selection.begin()->key); + Node *node = ObjectDB::get_instance(selection.begin()->key); + if (node) { + remove_node(node); + } } changed = true; diff --git a/editor/editor_data.h b/editor/editor_data.h index f578d55550e..9e5cca539ac 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -31,6 +31,7 @@ #pragma once #include "core/templates/list.h" +#include "scene/main/node.h" #include "scene/resources/texture.h" class ConfigFile; @@ -274,7 +275,7 @@ class EditorSelection : public Object { // Contains the selected nodes and corresponding metadata. // Metadata objects come from calling _get_editor_data on the editor_plugins, passing the selected node. - HashMap selection; + HashMap selection; // Tracks whether the selection change signal has been emitted. // Prevents multiple signals being called in one frame. @@ -287,7 +288,7 @@ class EditorSelection : public Object { // Editor plugins which are related to selection. List editor_plugins; - List top_selected_node_list; + LocalVector top_selected_node_list; void _update_node_list(); void _emit_change(); @@ -302,10 +303,14 @@ public: template T *get_node_editor_data(Node *p_node) { - if (!selection.has(p_node)) { + if (!p_node) { return nullptr; } - return Object::cast_to(selection[p_node]); + ObjectID nid = p_node->get_instance_id(); + if (!selection.has(nid)) { + return nullptr; + } + return Object::cast_to(selection[nid]); } // Adds an editor plugin which can provide metadata for selected nodes. @@ -316,7 +321,7 @@ public: // Returns only the top level selected nodes. // That is, if the selection includes some node and a child of that node, only the parent is returned. - const List &get_top_selected_node_list(); + List get_top_selected_node_list(); // Same as get_top_selected_node_list but returns a copy in a TypedArray for binding to scripts. TypedArray get_top_selected_nodes(); // Returns all the selected nodes (list version of "get_selected_nodes"). @@ -324,7 +329,7 @@ public: // Same as get_full_selected_node_list but returns a copy in a TypedArray for binding to scripts. TypedArray get_selected_nodes(); // Returns the map of selected objects and their metadata. - HashMap &get_selection() { return selection; } + HashMap &get_selection() { return selection; } ~EditorSelection(); }; diff --git a/editor/scene/2d/particles_2d_editor_plugin.cpp b/editor/scene/2d/particles_2d_editor_plugin.cpp index c5c69990d27..5daee85c2d0 100644 --- a/editor/scene/2d/particles_2d_editor_plugin.cpp +++ b/editor/scene/2d/particles_2d_editor_plugin.cpp @@ -341,12 +341,13 @@ void Particles2DEditorPlugin::_selection_changed() { } // Turn gizmos on for nodes that are newly selected. - HashSet nodes_in_current_selection; + HashSet nodes_in_current_selection; for (Node *node : current_selection) { - nodes_in_current_selection.insert(node); - if (!selected_particles.has(node)) { + ObjectID nid = node->get_instance_id(); + nodes_in_current_selection.insert(nid); + if (!selected_particles.has(nid)) { _set_show_gizmos(node, true); - selected_particles.insert(node); + selected_particles.insert(nid); } } @@ -358,21 +359,24 @@ void Particles2DEditorPlugin::_selection_changed() { direction_img_path_line_edit->set_text(""); // Turn gizmos off for nodes that are no longer selected. - LocalVector to_erase; - for (Node *node : selected_particles) { - if (!nodes_in_current_selection.has(node)) { - _set_show_gizmos(node, false); - to_erase.push_back(node); + LocalVector to_erase; + for (const ObjectID &nid : selected_particles) { + if (!nodes_in_current_selection.has(nid)) { + Node *node = ObjectDB::get_instance(nid); + if (node) { + _set_show_gizmos(node, false); + } + to_erase.push_back(nid); } } - for (Node *node : to_erase) { - selected_particles.erase(node); + for (const ObjectID &nid : to_erase) { + selected_particles.erase(nid); } } void Particles2DEditorPlugin::_node_removed(Node *p_node) { - if (selected_particles.erase(p_node)) { + if (p_node && selected_particles.erase(p_node->get_instance_id())) { _set_show_gizmos(p_node, false); } } diff --git a/editor/scene/2d/particles_2d_editor_plugin.h b/editor/scene/2d/particles_2d_editor_plugin.h index 765f6a863e5..e5a12c19202 100644 --- a/editor/scene/2d/particles_2d_editor_plugin.h +++ b/editor/scene/2d/particles_2d_editor_plugin.h @@ -44,7 +44,7 @@ protected: MENU_LOAD_EMISSION_MASK = 100, }; - HashSet selected_particles; + HashSet selected_particles; enum EmissionMode { EMISSION_MODE_SOLID, diff --git a/editor/scene/3d/node_3d_editor_plugin.cpp b/editor/scene/3d/node_3d_editor_plugin.cpp index eea4a9703cc..09b6826fa47 100644 --- a/editor/scene/3d/node_3d_editor_plugin.cpp +++ b/editor/scene/3d/node_3d_editor_plugin.cpp @@ -673,12 +673,12 @@ Transform3D Node3DEditorViewport::to_camera_transform(const Cursor &p_cursor) co } int Node3DEditorViewport::get_selected_count() const { - const HashMap &selection = editor_selection->get_selection(); + const HashMap &selection = editor_selection->get_selection(); int count = 0; - for (const KeyValue &E : selection) { - Node3D *sp = Object::cast_to(E.key); + for (const KeyValue &E : selection) { + Node3D *sp = ObjectDB::get_instance(E.key); if (!sp) { continue; } @@ -3341,13 +3341,13 @@ void Node3DEditorViewport::_notification(int p_what) { _update_camera(delta); } - const HashMap &selection = editor_selection->get_selection(); + const HashMap &selection = editor_selection->get_selection(); bool changed = false; bool exist = false; - for (const KeyValue &E : selection) { - Node3D *sp = Object::cast_to(E.key); + for (const KeyValue &E : selection) { + Node3D *sp = ObjectDB::get_instance(E.key); if (!sp) { continue; } @@ -8489,10 +8489,10 @@ void Node3DEditor::update_grid() { void Node3DEditor::_selection_changed() { _refresh_menu_icons(); - const HashMap &selection = editor_selection->get_selection(); + const HashMap &selection = editor_selection->get_selection(); - for (const KeyValue &E : selection) { - Node3D *sp = Object::cast_to(E.key); + for (const KeyValue &E : selection) { + Node3D *sp = ObjectDB::get_instance(E.key); if (!sp) { continue; } diff --git a/editor/scene/canvas_item_editor_plugin.cpp b/editor/scene/canvas_item_editor_plugin.cpp index 6d3469e541e..f678d71b13e 100644 --- a/editor/scene/canvas_item_editor_plugin.cpp +++ b/editor/scene/canvas_item_editor_plugin.cpp @@ -824,8 +824,8 @@ bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_po List CanvasItemEditor::_get_edited_canvas_items(bool p_retrieve_locked, bool p_remove_canvas_item_if_parent_in_selection, bool *r_has_locked_items) const { List selection; - for (const KeyValue &E : editor_selection->get_selection()) { - CanvasItem *ci = Object::cast_to(E.key); + for (const KeyValue &E : editor_selection->get_selection()) { + CanvasItem *ci = ObjectDB::get_instance(E.key); if (ci) { if (ci->is_visible_in_tree() && (p_retrieve_locked || !_is_node_locked(ci))) { Viewport *vp = ci->get_viewport(); @@ -4667,7 +4667,7 @@ void CanvasItemEditor::_button_tool_select(int p_index) { } void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation, bool p_scale, bool p_on_existing) { - const HashMap &selection = editor_selection->get_selection(); + const HashMap &selection = editor_selection->get_selection(); AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor(); ERR_FAIL_COND_MSG(te->get_current_animation().is_null(), "Cannot insert animation key. No animation selected."); @@ -4678,8 +4678,8 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation, return; } te->make_insert_queue(); - for (const KeyValue &E : selection) { - CanvasItem *ci = Object::cast_to(E.key); + for (const KeyValue &E : selection) { + CanvasItem *ci = ObjectDB::get_instance(E.key); if (!ci || !ci->is_visible_in_tree()) { continue; } @@ -4981,10 +4981,10 @@ void CanvasItemEditor::_popup_callback(int p_op) { case ANIM_COPY_POSE: { pose_clipboard.clear(); - const HashMap &selection = editor_selection->get_selection(); + const HashMap &selection = editor_selection->get_selection(); - for (const KeyValue &E : selection) { - CanvasItem *ci = Object::cast_to(E.key); + for (const KeyValue &E : selection) { + CanvasItem *ci = ObjectDB::get_instance(E.key); if (!ci || !ci->is_visible_in_tree()) { continue; } @@ -5023,10 +5023,10 @@ void CanvasItemEditor::_popup_callback(int p_op) { } break; case ANIM_CLEAR_POSE: { - HashMap &selection = editor_selection->get_selection(); + HashMap &selection = editor_selection->get_selection(); - for (const KeyValue &E : selection) { - CanvasItem *ci = Object::cast_to(E.key); + for (const KeyValue &E : selection) { + CanvasItem *ci = ObjectDB::get_instance(E.key); if (!ci || !ci->is_visible_in_tree()) { continue; } @@ -5089,7 +5089,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { } break; case SKELETON_MAKE_BONES: { - HashMap &selection = editor_selection->get_selection(); + HashMap &selection = editor_selection->get_selection(); Node *editor_root = get_tree()->get_edited_scene_root(); if (!editor_root || selection.is_empty()) { @@ -5097,8 +5097,8 @@ void CanvasItemEditor::_popup_callback(int p_op) { } undo_redo->create_action(TTR("Create Custom Bone2D(s) from Node(s)")); - for (const KeyValue &E : selection) { - Node2D *n2d = Object::cast_to(E.key); + for (const KeyValue &E : selection) { + Node2D *n2d = ObjectDB::get_instance(E.key); if (!n2d) { continue; } @@ -5144,9 +5144,9 @@ void CanvasItemEditor::_focus_selection(int p_op) { Rect2 rect; int count = 0; - const HashMap &selection = editor_selection->get_selection(); - for (const KeyValue &E : selection) { - CanvasItem *ci = Object::cast_to(E.key); + const HashMap &selection = editor_selection->get_selection(); + for (const KeyValue &E : selection) { + CanvasItem *ci = ObjectDB::get_instance(E.key); if (!ci) { continue; } diff --git a/editor/scene/gui/control_editor_plugin.cpp b/editor/scene/gui/control_editor_plugin.cpp index 69b55feeeac..4bf91f52331 100644 --- a/editor/scene/gui/control_editor_plugin.cpp +++ b/editor/scene/gui/control_editor_plugin.cpp @@ -926,8 +926,8 @@ bool ControlEditorToolbar::_is_node_locked(const Node *p_node) { List ControlEditorToolbar::_get_edited_controls() { List selection; - for (const KeyValue &E : editor_selection->get_selection()) { - Control *control = Object::cast_to(E.key); + for (const KeyValue &E : editor_selection->get_selection()) { + Control *control = ObjectDB::get_instance(E.key); if (control && control->is_visible_in_tree() && control->get_viewport() == EditorNode::get_singleton()->get_scene_root() && !_is_node_locked(control)) { selection.push_back(control); } @@ -958,8 +958,8 @@ void ControlEditorToolbar::_selection_changed() { SIZE_EXPAND, }; - for (const KeyValue &E : editor_selection->get_selection()) { - Control *control = Object::cast_to(E.key); + for (const KeyValue &E : editor_selection->get_selection()) { + Control *control = ObjectDB::get_instance(E.key); if (!control) { continue; }