1/**************************************************************************/
2/* scene_tree_dock.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "scene_tree_dock.h"
32
33#include "core/config/project_settings.h"
34#include "core/input/input.h"
35#include "core/io/resource_saver.h"
36#include "core/object/class_db.h"
37#include "core/object/message_queue.h"
38#include "core/os/keyboard.h"
39#include "editor/debugger/editor_debugger_node.h"
40#include "editor/editor_feature_profile.h"
41#include "editor/editor_node.h"
42#include "editor/editor_paths.h"
43#include "editor/editor_quick_open.h"
44#include "editor/editor_scale.h"
45#include "editor/editor_settings.h"
46#include "editor/editor_string_names.h"
47#include "editor/editor_undo_redo_manager.h"
48#include "editor/gui/editor_file_dialog.h"
49#include "editor/inspector_dock.h"
50#include "editor/multi_node_edit.h"
51#include "editor/plugins/animation_player_editor_plugin.h"
52#include "editor/plugins/canvas_item_editor_plugin.h"
53#include "editor/plugins/node_3d_editor_plugin.h"
54#include "editor/plugins/script_editor_plugin.h"
55#include "editor/reparent_dialog.h"
56#include "editor/shader_create_dialog.h"
57#include "scene/gui/check_box.h"
58#include "scene/main/window.h"
59#include "scene/property_utils.h"
60#include "scene/resources/packed_scene.h"
61#include "servers/display_server.h"
62#include "servers/rendering_server.h"
63
64#include "modules/modules_enabled.gen.h" // For regex.
65#ifdef MODULE_REGEX_ENABLED
66#include "editor/rename_dialog.h"
67#endif // MODULE_REGEX_ENABLED
68
69void SceneTreeDock::_nodes_drag_begin() {
70 pending_click_select = nullptr;
71}
72
73void SceneTreeDock::_quick_open() {
74 instantiate_scenes(quick_open->get_selected_files(), scene_tree->get_selected());
75}
76
77void SceneTreeDock::input(const Ref<InputEvent> &p_event) {
78 ERR_FAIL_COND(p_event.is_null());
79
80 Ref<InputEventMouseButton> mb = p_event;
81
82 if (mb.is_valid() && (mb->get_button_index() == MouseButton::LEFT || mb->get_button_index() == MouseButton::RIGHT)) {
83 if (mb->is_pressed() && scene_tree->get_rect().has_point(scene_tree->get_local_mouse_position())) {
84 tree_clicked = true;
85 } else if (!mb->is_pressed()) {
86 tree_clicked = false;
87 }
88
89 if (!mb->is_pressed() && pending_click_select) {
90 _push_item(pending_click_select);
91 pending_click_select = nullptr;
92 }
93 }
94}
95
96void SceneTreeDock::shortcut_input(const Ref<InputEvent> &p_event) {
97 ERR_FAIL_COND(p_event.is_null());
98
99 if (get_viewport()->gui_get_focus_owner() && get_viewport()->gui_get_focus_owner()->is_text_field()) {
100 return;
101 }
102
103 if (!p_event->is_pressed() || p_event->is_echo()) {
104 return;
105 }
106
107 if (ED_IS_SHORTCUT("scene_tree/rename", p_event)) {
108 _tool_selected(TOOL_RENAME);
109#ifdef MODULE_REGEX_ENABLED
110 } else if (ED_IS_SHORTCUT("scene_tree/batch_rename", p_event)) {
111 _tool_selected(TOOL_BATCH_RENAME);
112#endif // MODULE_REGEX_ENABLED
113 } else if (ED_IS_SHORTCUT("scene_tree/add_child_node", p_event)) {
114 _tool_selected(TOOL_NEW);
115 } else if (ED_IS_SHORTCUT("scene_tree/instantiate_scene", p_event)) {
116 _tool_selected(TOOL_INSTANTIATE);
117 } else if (ED_IS_SHORTCUT("scene_tree/expand_collapse_all", p_event)) {
118 _tool_selected(TOOL_EXPAND_COLLAPSE);
119 } else if (ED_IS_SHORTCUT("scene_tree/cut_node", p_event)) {
120 _tool_selected(TOOL_CUT);
121 } else if (ED_IS_SHORTCUT("scene_tree/copy_node", p_event)) {
122 _tool_selected(TOOL_COPY);
123 } else if (ED_IS_SHORTCUT("scene_tree/paste_node", p_event)) {
124 _tool_selected(TOOL_PASTE);
125 } else if (ED_IS_SHORTCUT("scene_tree/paste_node_as_sibling", p_event)) {
126 _tool_selected(TOOL_PASTE_AS_SIBLING);
127 } else if (ED_IS_SHORTCUT("scene_tree/change_node_type", p_event)) {
128 _tool_selected(TOOL_REPLACE);
129 } else if (ED_IS_SHORTCUT("scene_tree/duplicate", p_event)) {
130 _tool_selected(TOOL_DUPLICATE);
131 } else if (ED_IS_SHORTCUT("scene_tree/attach_script", p_event)) {
132 _tool_selected(TOOL_ATTACH_SCRIPT);
133 } else if (ED_IS_SHORTCUT("scene_tree/detach_script", p_event)) {
134 _tool_selected(TOOL_DETACH_SCRIPT);
135 } else if (ED_IS_SHORTCUT("scene_tree/move_up", p_event)) {
136 _tool_selected(TOOL_MOVE_UP);
137 } else if (ED_IS_SHORTCUT("scene_tree/move_down", p_event)) {
138 _tool_selected(TOOL_MOVE_DOWN);
139 } else if (ED_IS_SHORTCUT("scene_tree/reparent", p_event)) {
140 _tool_selected(TOOL_REPARENT);
141 } else if (ED_IS_SHORTCUT("scene_tree/reparent_to_new_node", p_event)) {
142 _tool_selected(TOOL_REPARENT_TO_NEW_NODE);
143 } else if (ED_IS_SHORTCUT("scene_tree/save_branch_as_scene", p_event)) {
144 _tool_selected(TOOL_NEW_SCENE_FROM);
145 } else if (ED_IS_SHORTCUT("scene_tree/delete_no_confirm", p_event)) {
146 _tool_selected(TOOL_ERASE, true);
147 } else if (ED_IS_SHORTCUT("scene_tree/copy_node_path", p_event)) {
148 _tool_selected(TOOL_COPY_NODE_PATH);
149 } else if (ED_IS_SHORTCUT("scene_tree/toggle_unique_name", p_event)) {
150 _tool_selected(TOOL_TOGGLE_SCENE_UNIQUE_NAME);
151 } else if (ED_IS_SHORTCUT("scene_tree/delete", p_event)) {
152 _tool_selected(TOOL_ERASE);
153 } else {
154 return;
155 }
156
157 // Tool selection was successful, accept the event to stop propagation.
158 accept_event();
159}
160
161void SceneTreeDock::instantiate(const String &p_file) {
162 Vector<String> scenes;
163 scenes.push_back(p_file);
164 instantiate_scenes(scenes, scene_tree->get_selected());
165}
166
167void SceneTreeDock::instantiate_scenes(const Vector<String> &p_files, Node *p_parent) {
168 Node *parent = p_parent;
169
170 if (!parent) {
171 parent = scene_tree->get_selected();
172 }
173
174 if (!parent) {
175 parent = edited_scene;
176 }
177
178 if (!parent) {
179 if (p_files.size() == 1) {
180 accept->set_text(TTR("No parent to instantiate a child at."));
181 } else {
182 accept->set_text(TTR("No parent to instantiate the scenes at."));
183 }
184 accept->popup_centered();
185 return;
186 };
187
188 _perform_instantiate_scenes(p_files, parent, -1);
189}
190
191void SceneTreeDock::_perform_instantiate_scenes(const Vector<String> &p_files, Node *parent, int p_pos) {
192 ERR_FAIL_NULL(parent);
193
194 Vector<Node *> instances;
195
196 bool error = false;
197
198 for (int i = 0; i < p_files.size(); i++) {
199 Ref<PackedScene> sdata = ResourceLoader::load(p_files[i]);
200 if (!sdata.is_valid()) {
201 current_option = -1;
202 accept->set_text(vformat(TTR("Error loading scene from %s"), p_files[i]));
203 accept->popup_centered();
204 error = true;
205 break;
206 }
207
208 Node *instantiated_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
209 if (!instantiated_scene) {
210 current_option = -1;
211 accept->set_text(vformat(TTR("Error instantiating scene from %s"), p_files[i]));
212 accept->popup_centered();
213 error = true;
214 break;
215 }
216
217 if (!edited_scene->get_scene_file_path().is_empty()) {
218 if (_cyclical_dependency_exists(edited_scene->get_scene_file_path(), instantiated_scene)) {
219 accept->set_text(vformat(TTR("Cannot instantiate the scene '%s' because the current scene exists within one of its nodes."), p_files[i]));
220 accept->popup_centered();
221 error = true;
222 break;
223 }
224 }
225
226 instantiated_scene->set_scene_file_path(ProjectSettings::get_singleton()->localize_path(p_files[i]));
227
228 instances.push_back(instantiated_scene);
229 }
230
231 if (error) {
232 for (int i = 0; i < instances.size(); i++) {
233 memdelete(instances[i]);
234 }
235 return;
236 }
237
238 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
239 undo_redo->create_action(TTR("Instantiate Scene(s)"));
240
241 for (int i = 0; i < instances.size(); i++) {
242 Node *instantiated_scene = instances[i];
243
244 undo_redo->add_do_method(parent, "add_child", instantiated_scene, true);
245 if (p_pos >= 0) {
246 undo_redo->add_do_method(parent, "move_child", instantiated_scene, p_pos + i);
247 }
248 undo_redo->add_do_method(instantiated_scene, "set_owner", edited_scene);
249 undo_redo->add_do_method(editor_selection, "clear");
250 undo_redo->add_do_method(editor_selection, "add_node", instantiated_scene);
251 undo_redo->add_do_reference(instantiated_scene);
252 undo_redo->add_undo_method(parent, "remove_child", instantiated_scene);
253
254 String new_name = parent->validate_child_name(instantiated_scene);
255 EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
256 undo_redo->add_do_method(ed, "live_debug_instantiate_node", edited_scene->get_path_to(parent), p_files[i], new_name);
257 undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)).path_join(new_name)));
258 }
259
260 undo_redo->commit_action();
261 _push_item(instances[instances.size() - 1]);
262 for (int i = 0; i < instances.size(); i++) {
263 emit_signal(SNAME("node_created"), instances[i]);
264 }
265}
266
267void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base) {
268 // `move_child` + `get_index` doesn't really work for internal nodes.
269 ERR_FAIL_COND_MSG(base->get_internal_mode() != INTERNAL_MODE_DISABLED, "Trying to replace internal node, this is not supported.");
270
271 Ref<PackedScene> sdata = ResourceLoader::load(p_file);
272 if (!sdata.is_valid()) {
273 accept->set_text(vformat(TTR("Error loading scene from %s"), p_file));
274 accept->popup_centered();
275 return;
276 }
277
278 Node *instantiated_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
279 if (!instantiated_scene) {
280 accept->set_text(vformat(TTR("Error instantiating scene from %s"), p_file));
281 accept->popup_centered();
282 return;
283 }
284
285 instantiated_scene->set_unique_name_in_owner(base->is_unique_name_in_owner());
286
287 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
288 undo_redo->create_action(TTR("Replace with Branch Scene"));
289
290 Node *parent = base->get_parent();
291 int pos = base->get_index(false);
292 undo_redo->add_do_method(parent, "remove_child", base);
293 undo_redo->add_undo_method(parent, "remove_child", instantiated_scene);
294 undo_redo->add_do_method(parent, "add_child", instantiated_scene, true);
295 undo_redo->add_undo_method(parent, "add_child", base, true);
296 undo_redo->add_do_method(parent, "move_child", instantiated_scene, pos);
297 undo_redo->add_undo_method(parent, "move_child", base, pos);
298
299 List<Node *> owned;
300 base->get_owned_by(base->get_owner(), &owned);
301 Array owners;
302 for (Node *F : owned) {
303 owners.push_back(F);
304 }
305 undo_redo->add_do_method(instantiated_scene, "set_owner", edited_scene);
306 undo_redo->add_undo_method(this, "_set_owners", edited_scene, owners);
307
308 undo_redo->add_do_method(editor_selection, "clear");
309 undo_redo->add_undo_method(editor_selection, "clear");
310 undo_redo->add_do_method(editor_selection, "add_node", instantiated_scene);
311 undo_redo->add_undo_method(editor_selection, "add_node", base);
312 undo_redo->add_do_property(scene_tree, "set_selected", instantiated_scene);
313 undo_redo->add_undo_property(scene_tree, "set_selected", base);
314
315 undo_redo->add_do_reference(instantiated_scene);
316 undo_redo->add_undo_reference(base);
317 undo_redo->commit_action();
318}
319
320bool SceneTreeDock::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) {
321 int childCount = p_desired_node->get_child_count();
322
323 if (_track_inherit(p_target_scene_path, p_desired_node)) {
324 return true;
325 }
326
327 for (int i = 0; i < childCount; i++) {
328 Node *child = p_desired_node->get_child(i);
329
330 if (_cyclical_dependency_exists(p_target_scene_path, child)) {
331 return true;
332 }
333 }
334
335 return false;
336}
337
338bool SceneTreeDock::_track_inherit(const String &p_target_scene_path, Node *p_desired_node) {
339 Node *p = p_desired_node;
340 bool result = false;
341 Vector<Node *> instances;
342 while (true) {
343 if (p->get_scene_file_path() == p_target_scene_path) {
344 result = true;
345 break;
346 }
347 Ref<SceneState> ss = p->get_scene_inherited_state();
348 if (ss.is_valid()) {
349 String path = ss->get_path();
350 Ref<PackedScene> pack_data = ResourceLoader::load(path);
351 if (pack_data.is_valid()) {
352 p = pack_data->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE);
353 if (!p) {
354 continue;
355 }
356 instances.push_back(p);
357 } else {
358 break;
359 }
360 } else {
361 break;
362 }
363 }
364 for (int i = 0; i < instances.size(); i++) {
365 memdelete(instances[i]);
366 }
367 return result;
368}
369
370void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
371 current_option = p_tool;
372
373 switch (p_tool) {
374#ifdef MODULE_REGEX_ENABLED
375 case TOOL_BATCH_RENAME: {
376 if (!profile_allow_editing) {
377 break;
378 }
379 if (editor_selection->get_selected_node_list().size() > 1) {
380 rename_dialog->popup_centered();
381 }
382 } break;
383#endif // MODULE_REGEX_ENABLED
384 case TOOL_RENAME: {
385 if (!profile_allow_editing) {
386 break;
387 }
388 Tree *tree = scene_tree->get_scene_tree();
389 if (tree->is_anything_selected()) {
390 tree->grab_focus();
391 tree->edit_selected();
392 }
393 } break;
394 case TOOL_REPARENT_TO_NEW_NODE:
395 if (!_validate_no_foreign()) {
396 break;
397 }
398 [[fallthrough]];
399 case TOOL_NEW: {
400 if (!profile_allow_editing) {
401 break;
402 }
403
404 if (reset_create_dialog && !p_confirm_override) {
405 create_dialog->set_base_type("Node");
406 reset_create_dialog = false;
407 }
408
409 // Prefer nodes that inherit from the current scene root.
410 Node *current_edited_scene_root = EditorNode::get_singleton()->get_edited_scene();
411 if (current_edited_scene_root) {
412 String root_class = current_edited_scene_root->get_class_name();
413 static Vector<String> preferred_types;
414 if (preferred_types.is_empty()) {
415 preferred_types.push_back("Control");
416 preferred_types.push_back("Node2D");
417 preferred_types.push_back("Node3D");
418 }
419
420 for (int i = 0; i < preferred_types.size(); i++) {
421 if (ClassDB::is_parent_class(root_class, preferred_types[i])) {
422 create_dialog->set_preferred_search_result_type(preferred_types[i]);
423 break;
424 }
425 }
426 }
427
428 create_dialog->popup_create(true);
429 if (!p_confirm_override) {
430 emit_signal(SNAME("add_node_used"));
431 }
432 } break;
433 case TOOL_INSTANTIATE: {
434 if (!profile_allow_editing) {
435 break;
436 }
437 Node *scene = edited_scene;
438
439 if (!scene) {
440 EditorNode::get_singleton()->new_inherited_scene();
441 break;
442 }
443
444 quick_open->popup_dialog("PackedScene", true);
445 quick_open->set_title(TTR("Instantiate Child Scene"));
446 if (!p_confirm_override) {
447 emit_signal(SNAME("add_node_used"));
448 }
449 } break;
450 case TOOL_EXPAND_COLLAPSE: {
451 Tree *tree = scene_tree->get_scene_tree();
452 TreeItem *selected_item = tree->get_selected();
453
454 if (!selected_item) {
455 selected_item = tree->get_root();
456 if (!selected_item) {
457 break;
458 }
459 }
460
461 bool collapsed = selected_item->is_any_collapsed();
462 selected_item->set_collapsed_recursive(!collapsed);
463
464 tree->ensure_cursor_is_visible();
465
466 } break;
467 case TOOL_CUT:
468 case TOOL_COPY: {
469 if (!edited_scene || (p_tool == TOOL_CUT && !_validate_no_foreign())) {
470 break;
471 }
472
473 List<Node *> selection = editor_selection->get_selected_node_list();
474 if (selection.size() == 0) {
475 break;
476 }
477
478 bool was_empty = false;
479 if (!node_clipboard.is_empty()) {
480 _clear_clipboard();
481 } else {
482 was_empty = true;
483 }
484 clipboard_source_scene = EditorNode::get_singleton()->get_edited_scene()->get_scene_file_path();
485
486 selection.sort_custom<Node::Comparator>();
487
488 for (Node *node : selection) {
489 HashMap<const Node *, Node *> duplimap;
490 Node *dup = node->duplicate_from_editor(duplimap);
491
492 ERR_CONTINUE(!dup);
493
494 // Preserve ownership relations ready for pasting.
495 List<Node *> owned;
496 node->get_owned_by(node->get_owner() ? node->get_owner() : node, &owned);
497
498 for (Node *F : owned) {
499 if (!duplimap.has(F) || F == node) {
500 continue;
501 }
502 Node *d = duplimap[F];
503 // Only use this as a marker that ownership needs to be assigned when pasting.
504 // The actual owner doesn't matter.
505 d->set_owner(dup);
506 }
507
508 node_clipboard.push_back(dup);
509 }
510
511 if (p_tool == TOOL_CUT) {
512 _delete_confirm(true);
513 }
514
515 if (was_empty) {
516 _update_create_root_dialog();
517 }
518 } break;
519 case TOOL_PASTE: {
520 paste_nodes(false);
521 } break;
522 case TOOL_PASTE_AS_SIBLING: {
523 paste_nodes(true);
524 } break;
525 case TOOL_REPLACE: {
526 if (!profile_allow_editing) {
527 break;
528 }
529
530 if (!_validate_no_foreign()) {
531 break;
532 }
533
534 if (!_validate_no_instance()) {
535 break;
536 }
537
538 if (reset_create_dialog) {
539 create_dialog->set_base_type("Node");
540 reset_create_dialog = false;
541 }
542
543 Node *selected = scene_tree->get_selected();
544 if (!selected && !editor_selection->get_selected_node_list().is_empty()) {
545 selected = editor_selection->get_selected_node_list().front()->get();
546 }
547
548 if (selected) {
549 create_dialog->popup_create(false, true, selected->get_class(), selected->get_name());
550 }
551 } break;
552 case TOOL_EXTEND_SCRIPT: {
553 attach_script_to_selected(true);
554 } break;
555 case TOOL_ATTACH_SCRIPT: {
556 attach_script_to_selected(false);
557 } break;
558 case TOOL_DETACH_SCRIPT: {
559 if (!profile_allow_script_editing) {
560 break;
561 }
562
563 Array selection = editor_selection->get_selected_nodes();
564
565 if (selection.is_empty()) {
566 return;
567 }
568
569 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
570 undo_redo->create_action(TTR("Detach Script"), UndoRedo::MERGE_DISABLE, EditorNode::get_singleton()->get_edited_scene());
571 undo_redo->add_do_method(EditorNode::get_singleton(), "push_item", (Script *)nullptr);
572
573 for (int i = 0; i < selection.size(); i++) {
574 Node *n = Object::cast_to<Node>(selection[i]);
575 Ref<Script> existing = n->get_script();
576 Ref<Script> empty = EditorNode::get_singleton()->get_object_custom_type_base(n);
577 if (existing != empty) {
578 undo_redo->add_do_method(n, "set_script", empty);
579 undo_redo->add_undo_method(n, "set_script", existing);
580 }
581 }
582
583 undo_redo->add_do_method(this, "_update_script_button");
584 undo_redo->add_undo_method(this, "_update_script_button");
585
586 undo_redo->commit_action();
587 } break;
588 case TOOL_MOVE_UP:
589 case TOOL_MOVE_DOWN: {
590 if (!profile_allow_editing) {
591 break;
592 }
593
594 if (!scene_tree->get_selected()) {
595 break;
596 }
597
598 if (scene_tree->get_selected() == edited_scene) {
599 current_option = -1;
600 accept->set_text(TTR("This operation can't be done on the tree root."));
601 accept->popup_centered();
602 break;
603 }
604
605 if (!_validate_no_foreign()) {
606 break;
607 }
608
609 bool MOVING_DOWN = (p_tool == TOOL_MOVE_DOWN);
610 bool MOVING_UP = !MOVING_DOWN;
611
612 Node *common_parent = scene_tree->get_selected()->get_parent();
613 List<Node *> selection = editor_selection->get_selected_node_list();
614 selection.sort_custom<Node::Comparator>(); // sort by index
615 if (MOVING_DOWN) {
616 selection.reverse();
617 }
618
619 int lowest_id = common_parent->get_child_count(false) - 1;
620 int highest_id = 0;
621 for (Node *E : selection) {
622 // `move_child` + `get_index` doesn't really work for internal nodes.
623 ERR_FAIL_COND_MSG(E->get_internal_mode() != INTERNAL_MODE_DISABLED, "Trying to move internal node, this is not supported.");
624 int index = E->get_index(false);
625
626 if (index > highest_id) {
627 highest_id = index;
628 }
629 if (index < lowest_id) {
630 lowest_id = index;
631 }
632
633 if (E->get_parent() != common_parent) {
634 common_parent = nullptr;
635 }
636 }
637
638 if (!common_parent || (MOVING_DOWN && highest_id >= common_parent->get_child_count(false) - MOVING_DOWN) || (MOVING_UP && lowest_id == 0)) {
639 break; // one or more nodes can not be moved
640 }
641
642 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
643 if (selection.size() == 1) {
644 undo_redo->create_action(TTR("Move Node In Parent"));
645 }
646 if (selection.size() > 1) {
647 undo_redo->create_action(TTR("Move Nodes In Parent"));
648 }
649
650 for (int i = 0; i < selection.size(); i++) {
651 Node *top_node = selection[i];
652 Node *bottom_node = selection[selection.size() - 1 - i];
653
654 ERR_FAIL_COND(!top_node->get_parent());
655 ERR_FAIL_COND(!bottom_node->get_parent());
656
657 int bottom_node_pos = bottom_node->get_index(false);
658 int top_node_pos_next = top_node->get_index(false) + (MOVING_DOWN ? 1 : -1);
659
660 undo_redo->add_do_method(top_node->get_parent(), "move_child", top_node, top_node_pos_next);
661 undo_redo->add_undo_method(bottom_node->get_parent(), "move_child", bottom_node, bottom_node_pos);
662 }
663
664 undo_redo->commit_action();
665
666 } break;
667 case TOOL_DUPLICATE: {
668 if (!profile_allow_editing) {
669 break;
670 }
671
672 if (!edited_scene) {
673 break;
674 }
675
676 if (editor_selection->is_selected(edited_scene)) {
677 current_option = -1;
678 accept->set_text(TTR("This operation can't be done on the tree root."));
679 accept->popup_centered();
680 break;
681 }
682
683 if (!_validate_no_foreign()) {
684 break;
685 }
686
687 List<Node *> selection = editor_selection->get_selected_node_list();
688 if (selection.size() == 0) {
689 break;
690 }
691
692 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
693 undo_redo->create_action(TTR("Duplicate Node(s)"), UndoRedo::MERGE_DISABLE, selection.front()->get());
694 undo_redo->add_do_method(editor_selection, "clear");
695
696 Node *dupsingle = nullptr;
697
698 selection.sort_custom<Node::Comparator>();
699
700 Node *add_below_node = selection.back()->get();
701
702 for (Node *node : selection) {
703 Node *parent = node->get_parent();
704
705 List<Node *> owned;
706 node->get_owned_by(node->get_owner(), &owned);
707
708 HashMap<const Node *, Node *> duplimap;
709 Node *dup = node->duplicate_from_editor(duplimap);
710
711 ERR_CONTINUE(!dup);
712
713 if (selection.size() == 1) {
714 dupsingle = dup;
715 }
716
717 dup->set_name(parent->validate_child_name(dup));
718
719 undo_redo->add_do_method(add_below_node, "add_sibling", dup, true);
720
721 for (Node *F : owned) {
722 if (!duplimap.has(F)) {
723 continue;
724 }
725 Node *d = duplimap[F];
726 undo_redo->add_do_method(d, "set_owner", node->get_owner());
727 }
728 undo_redo->add_do_method(editor_selection, "add_node", dup);
729 undo_redo->add_undo_method(parent, "remove_child", dup);
730 undo_redo->add_do_reference(dup);
731
732 EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
733
734 undo_redo->add_do_method(ed, "live_debug_duplicate_node", edited_scene->get_path_to(node), dup->get_name());
735 undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)).path_join(dup->get_name())));
736
737 add_below_node = dup;
738 }
739
740 undo_redo->commit_action();
741
742 if (dupsingle) {
743 _push_item(dupsingle);
744 }
745 } break;
746 case TOOL_REPARENT: {
747 if (!profile_allow_editing) {
748 break;
749 }
750
751 if (!scene_tree->get_selected()) {
752 break;
753 }
754
755 if (editor_selection->is_selected(edited_scene)) {
756 current_option = -1;
757 accept->set_text(TTR("This operation can't be done on the tree root."));
758 accept->popup_centered();
759 break;
760 }
761
762 if (!_validate_no_foreign()) {
763 break;
764 }
765
766 List<Node *> nodes = editor_selection->get_selected_node_list();
767 HashSet<Node *> nodeset;
768 for (Node *E : nodes) {
769 nodeset.insert(E);
770 }
771 reparent_dialog->set_current(nodeset);
772 reparent_dialog->popup_centered_clamped(Size2(350, 700) * EDSCALE);
773 } break;
774 case TOOL_MAKE_ROOT: {
775 if (!profile_allow_editing) {
776 break;
777 }
778
779 List<Node *> nodes = editor_selection->get_selected_node_list();
780 ERR_FAIL_COND(nodes.size() != 1);
781
782 Node *node = nodes.front()->get();
783 Node *root = get_tree()->get_edited_scene_root();
784
785 if (node == root) {
786 return;
787 }
788
789 // `move_child` + `get_index` doesn't really work for internal nodes.
790 ERR_FAIL_COND_MSG(node->get_internal_mode() != INTERNAL_MODE_DISABLED, "Trying to set internal node as scene root, this is not supported.");
791
792 //check that from node to root, all owners are right
793
794 if (root->get_scene_inherited_state().is_valid()) {
795 accept->set_text(TTR("Can't reparent nodes in inherited scenes, order of nodes can't change."));
796 accept->popup_centered();
797 return;
798 }
799
800 if (node->get_owner() != root) {
801 accept->set_text(TTR("Node must belong to the edited scene to become root."));
802 accept->popup_centered();
803 return;
804 }
805
806 if (!node->get_scene_file_path().is_empty()) {
807 accept->set_text(TTR("Instantiated scenes can't become root"));
808 accept->popup_centered();
809 return;
810 }
811
812 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
813 undo_redo->create_action(TTR("Make node as Root"));
814 undo_redo->add_do_method(node->get_parent(), "remove_child", node);
815 undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", node);
816 undo_redo->add_do_method(node, "add_child", root, true);
817 undo_redo->add_do_method(node, "set_scene_file_path", root->get_scene_file_path());
818 undo_redo->add_do_method(root, "set_scene_file_path", String());
819 undo_redo->add_do_method(node, "set_owner", (Object *)nullptr);
820 undo_redo->add_do_method(root, "set_owner", node);
821 _node_replace_owner(root, root, node, MODE_DO);
822
823 undo_redo->add_undo_method(root, "set_scene_file_path", root->get_scene_file_path());
824 undo_redo->add_undo_method(node, "set_scene_file_path", String());
825 undo_redo->add_undo_method(node, "remove_child", root);
826 undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", root);
827 undo_redo->add_undo_method(node->get_parent(), "add_child", node, true);
828 undo_redo->add_undo_method(node->get_parent(), "move_child", node, node->get_index(false));
829 undo_redo->add_undo_method(root, "set_owner", (Object *)nullptr);
830 undo_redo->add_undo_method(node, "set_owner", root);
831 _node_replace_owner(root, root, root, MODE_UNDO);
832
833 undo_redo->add_do_method(scene_tree, "update_tree");
834 undo_redo->add_undo_method(scene_tree, "update_tree");
835 undo_redo->commit_action();
836 } break;
837 case TOOL_MULTI_EDIT: {
838 if (!profile_allow_editing) {
839 break;
840 }
841
842 Node *root = EditorNode::get_singleton()->get_edited_scene();
843 if (!root) {
844 break;
845 }
846 Ref<MultiNodeEdit> mne = memnew(MultiNodeEdit);
847 for (const KeyValue<Node *, Object *> &E : editor_selection->get_selection()) {
848 mne->add_node(root->get_path_to(E.key));
849 }
850
851 _push_item(mne.ptr());
852
853 } break;
854
855 case TOOL_ERASE: {
856 if (!profile_allow_editing) {
857 break;
858 }
859
860 List<Node *> remove_list = editor_selection->get_selected_node_list();
861
862 if (remove_list.is_empty()) {
863 return;
864 }
865
866 if (!_validate_no_foreign()) {
867 break;
868 }
869
870 bool allow_ask_delete_tracks = EDITOR_GET("docks/scene_tree/ask_before_deleting_related_animation_tracks").operator bool();
871 bool has_tracks_to_delete = allow_ask_delete_tracks && _has_tracks_to_delete(edited_scene, remove_list);
872 if (p_confirm_override && !has_tracks_to_delete) {
873 _delete_confirm();
874 } else {
875 String msg;
876 if (remove_list.size() > 1) {
877 bool any_children = false;
878 for (int i = 0; !any_children && i < remove_list.size(); i++) {
879 any_children = remove_list[i]->get_child_count() > 0;
880 }
881
882 msg = vformat(any_children ? TTR("Delete %d nodes and any children?") : TTR("Delete %d nodes?"), remove_list.size());
883 } else {
884 if (!p_confirm_override) {
885 Node *node = remove_list[0];
886 if (node == editor_data->get_edited_scene_root()) {
887 msg = vformat(TTR("Delete the root node \"%s\"?"), node->get_name());
888 } else if (node->get_scene_file_path().is_empty() && node->get_child_count() > 0) {
889 // Display this message only for non-instantiated scenes
890 msg = vformat(TTR("Delete node \"%s\" and its children?"), node->get_name());
891 } else {
892 msg = vformat(TTR("Delete node \"%s\"?"), node->get_name());
893 }
894 }
895
896 if (has_tracks_to_delete) {
897 if (!msg.is_empty()) {
898 msg += "\n";
899 }
900 msg += TTR("Some nodes are referenced by animation tracks.");
901 delete_tracks_checkbox->show();
902 } else {
903 delete_tracks_checkbox->hide();
904 }
905 }
906
907 delete_dialog_label->set_text(msg);
908
909 // Resize the dialog to its minimum size.
910 // This prevents the dialog from being too wide after displaying
911 // a deletion confirmation for a node with a long name.
912 delete_dialog->reset_size();
913 delete_dialog->popup_centered();
914 }
915
916 } break;
917 case TOOL_NEW_SCENE_FROM: {
918 if (!profile_allow_editing) {
919 break;
920 }
921
922 Node *scene = editor_data->get_edited_scene_root();
923
924 if (!scene) {
925 accept->set_text(TTR("Saving the branch as a scene requires having a scene open in the editor."));
926 accept->popup_centered();
927 break;
928 }
929
930 List<Node *> selection = editor_selection->get_selected_node_list();
931
932 if (selection.size() != 1) {
933 accept->set_text(vformat(TTR("Saving the branch as a scene requires selecting only one node, but you have selected %d nodes."), selection.size()));
934 accept->popup_centered();
935 break;
936 }
937
938 Node *tocopy = selection.front()->get();
939
940 if (tocopy == scene) {
941 accept->set_text(TTR("Can't save the root node branch as an instantiated scene.\nTo create an editable copy of the current scene, duplicate it using the FileSystem dock context menu\nor create an inherited scene using Scene > New Inherited Scene... instead."));
942 accept->popup_centered();
943 break;
944 }
945
946 if (tocopy != editor_data->get_edited_scene_root() && !tocopy->get_scene_file_path().is_empty()) {
947 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."));
948 accept->popup_centered();
949 break;
950 }
951
952 if (tocopy->get_owner() != scene) {
953 accept->set_text(TTR("Can't save a branch which is a child of an already instantiated scene.\nTo save this branch into its own scene, open the original scene, right click on this branch, and select \"Save Branch as Scene\"."));
954 accept->popup_centered();
955 break;
956 }
957
958 if (scene->get_scene_inherited_state().is_valid() && scene->get_scene_inherited_state()->find_node_by_path(scene->get_path_to(tocopy)) >= 0) {
959 accept->set_text(TTR("Can't save a branch which is part of an inherited scene.\nTo save this branch into its own scene, open the original scene, right click on this branch, and select \"Save Branch as Scene\"."));
960 accept->popup_centered();
961 break;
962 }
963
964 new_scene_from_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
965
966 List<String> extensions;
967 Ref<PackedScene> sd = memnew(PackedScene);
968 ResourceSaver::get_recognized_extensions(sd, &extensions);
969 new_scene_from_dialog->clear_filters();
970 for (int i = 0; i < extensions.size(); i++) {
971 new_scene_from_dialog->add_filter("*." + extensions[i], extensions[i].to_upper());
972 }
973
974 String existing;
975 if (extensions.size()) {
976 String root_name(tocopy->get_name());
977 root_name = EditorNode::adjust_scene_name_casing(root_name);
978 existing = root_name + "." + extensions.front()->get().to_lower();
979 }
980 new_scene_from_dialog->set_current_path(existing);
981
982 new_scene_from_dialog->set_title(TTR("Save New Scene As..."));
983 new_scene_from_dialog->popup_file_dialog();
984 } break;
985 case TOOL_COPY_NODE_PATH: {
986 List<Node *> selection = editor_selection->get_selected_node_list();
987 List<Node *>::Element *e = selection.front();
988 if (e) {
989 Node *node = e->get();
990 if (node) {
991 Node *root = EditorNode::get_singleton()->get_edited_scene();
992 NodePath path = root->get_path().rel_path_to(node->get_path());
993 DisplayServer::get_singleton()->clipboard_set(path);
994 }
995 }
996 } break;
997 case TOOL_OPEN_DOCUMENTATION: {
998 List<Node *> selection = editor_selection->get_selected_node_list();
999 for (int i = 0; i < selection.size(); i++) {
1000 ScriptEditor::get_singleton()->goto_help("class_name:" + selection[i]->get_class());
1001 }
1002 EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
1003 } break;
1004 case TOOL_AUTO_EXPAND: {
1005 scene_tree->set_auto_expand_selected(!EDITOR_GET("docks/scene_tree/auto_expand_to_selected"), true);
1006 } break;
1007 case TOOL_SCENE_EDITABLE_CHILDREN: {
1008 if (!profile_allow_editing) {
1009 break;
1010 }
1011
1012 List<Node *> selection = editor_selection->get_selected_node_list();
1013 List<Node *>::Element *e = selection.front();
1014 if (e) {
1015 Node *node = e->get();
1016 if (node) {
1017 bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node);
1018
1019 if (editable) {
1020 editable_instance_remove_dialog->set_text(TTR("Disabling \"editable_instance\" will cause all properties of the node to be reverted to their default."));
1021 editable_instance_remove_dialog->popup_centered();
1022 break;
1023 }
1024 _toggle_editable_children(node);
1025 }
1026 }
1027 } break;
1028 case TOOL_SCENE_USE_PLACEHOLDER: {
1029 if (!profile_allow_editing) {
1030 break;
1031 }
1032
1033 List<Node *> selection = editor_selection->get_selected_node_list();
1034 List<Node *>::Element *e = selection.front();
1035 if (e) {
1036 Node *node = e->get();
1037 if (node) {
1038 bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node);
1039 bool placeholder = node->get_scene_instance_load_placeholder();
1040
1041 // Fire confirmation dialog when children are editable.
1042 if (editable && !placeholder) {
1043 placeholder_editable_instance_remove_dialog->set_text(TTR("Enabling \"Load As Placeholder\" will disable \"Editable Children\" and cause all properties of the node to be reverted to their default."));
1044 placeholder_editable_instance_remove_dialog->popup_centered();
1045 break;
1046 }
1047
1048 placeholder = !placeholder;
1049
1050 if (placeholder) {
1051 EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node, false);
1052 }
1053
1054 node->set_scene_instance_load_placeholder(placeholder);
1055 scene_tree->update_tree();
1056 }
1057 }
1058 } break;
1059 case TOOL_SCENE_MAKE_LOCAL: {
1060 if (!profile_allow_editing) {
1061 break;
1062 }
1063
1064 List<Node *> selection = editor_selection->get_selected_node_list();
1065 List<Node *>::Element *e = selection.front();
1066 if (e) {
1067 Node *node = e->get();
1068 if (node) {
1069 Node *root = EditorNode::get_singleton()->get_edited_scene();
1070 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
1071 if (!root) {
1072 break;
1073 }
1074
1075 ERR_FAIL_COND(node->get_scene_file_path().is_empty());
1076 undo_redo->create_action(TTR("Make Local"));
1077 undo_redo->add_do_method(node, "set_scene_file_path", "");
1078 undo_redo->add_undo_method(node, "set_scene_file_path", node->get_scene_file_path());
1079 _node_replace_owner(node, node, root);
1080 undo_redo->add_do_method(scene_tree, "update_tree");
1081 undo_redo->add_undo_method(scene_tree, "update_tree");
1082 undo_redo->commit_action();
1083 }
1084 }
1085 } break;
1086 case TOOL_SCENE_OPEN: {
1087 List<Node *> selection = editor_selection->get_selected_node_list();
1088 List<Node *>::Element *e = selection.front();
1089 if (e) {
1090 Node *node = e->get();
1091 if (node) {
1092 scene_tree->emit_signal(SNAME("open"), node->get_scene_file_path());
1093 }
1094 }
1095 } break;
1096 case TOOL_SCENE_CLEAR_INHERITANCE: {
1097 if (!profile_allow_editing) {
1098 break;
1099 }
1100
1101 clear_inherit_confirm->popup_centered();
1102 } break;
1103 case TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM: {
1104 if (!profile_allow_editing) {
1105 break;
1106 }
1107
1108 List<Node *> selection = editor_selection->get_selected_node_list();
1109 List<Node *>::Element *e = selection.front();
1110 if (e) {
1111 Node *node = e->get();
1112 if (node) {
1113 node->set_scene_inherited_state(Ref<SceneState>());
1114 scene_tree->update_tree();
1115 InspectorDock::get_inspector_singleton()->update_tree();
1116 }
1117 }
1118 } break;
1119 case TOOL_SCENE_OPEN_INHERITED: {
1120 List<Node *> selection = editor_selection->get_selected_node_list();
1121 List<Node *>::Element *e = selection.front();
1122 if (e) {
1123 Node *node = e->get();
1124 if (node && node->get_scene_inherited_state().is_valid()) {
1125 scene_tree->emit_signal(SNAME("open"), node->get_scene_inherited_state()->get_path());
1126 }
1127 }
1128 } break;
1129 case TOOL_TOGGLE_SCENE_UNIQUE_NAME: {
1130 // Enabling/disabling based on the same node based on which the checkbox in the menu is checked/unchecked.
1131 List<Node *>::Element *first_selected = editor_selection->get_selected_node_list().front();
1132 if (first_selected == nullptr) {
1133 return;
1134 }
1135 if (first_selected->get() == EditorNode::get_singleton()->get_edited_scene()) {
1136 // Exclude Root Node. It should never be unique name in its own scene!
1137 editor_selection->remove_node(first_selected->get());
1138 first_selected = editor_selection->get_selected_node_list().front();
1139 if (first_selected == nullptr) {
1140 return;
1141 }
1142 }
1143 bool enabling = !first_selected->get()->is_unique_name_in_owner();
1144
1145 List<Node *> full_selection = editor_selection->get_full_selected_node_list();
1146 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
1147
1148 if (enabling) {
1149 Vector<Node *> new_unique_nodes;
1150 Vector<StringName> new_unique_names;
1151 Vector<StringName> cant_be_set_unique_names;
1152
1153 for (Node *node : full_selection) {
1154 if (node->is_unique_name_in_owner()) {
1155 continue;
1156 }
1157 StringName name = node->get_name();
1158 if (new_unique_names.find(name) != -1 || get_tree()->get_edited_scene_root()->get_node_or_null(UNIQUE_NODE_PREFIX + String(name)) != nullptr) {
1159 cant_be_set_unique_names.push_back(name);
1160 } else {
1161 new_unique_nodes.push_back(node);
1162 new_unique_names.push_back(name);
1163 }
1164 }
1165
1166 if (new_unique_nodes.size()) {
1167 undo_redo->create_action(TTR("Enable Scene Unique Name(s)"));
1168 for (Node *node : new_unique_nodes) {
1169 undo_redo->add_do_method(node, "set_unique_name_in_owner", true);
1170 undo_redo->add_undo_method(node, "set_unique_name_in_owner", false);
1171 }
1172 undo_redo->commit_action();
1173 }
1174
1175 if (cant_be_set_unique_names.size()) {
1176 String popup_text = TTR("Unique names already used by another node in the scene:");
1177 popup_text += "\n";
1178 for (StringName name : cant_be_set_unique_names) {
1179 popup_text += "\n" + String(name);
1180 }
1181 accept->set_text(popup_text);
1182 accept->popup_centered();
1183 }
1184 } else { // Disabling.
1185 undo_redo->create_action(TTR("Disable Scene Unique Name(s)"));
1186 for (Node *node : full_selection) {
1187 if (!node->is_unique_name_in_owner()) {
1188 continue;
1189 }
1190 undo_redo->add_do_method(node, "set_unique_name_in_owner", false);
1191 undo_redo->add_undo_method(node, "set_unique_name_in_owner", true);
1192 }
1193 undo_redo->commit_action();
1194 }
1195 } break;
1196 case TOOL_CREATE_2D_SCENE:
1197 case TOOL_CREATE_3D_SCENE:
1198 case TOOL_CREATE_USER_INTERFACE:
1199 case TOOL_CREATE_FAVORITE: {
1200 Node *new_node = nullptr;
1201
1202 if (TOOL_CREATE_FAVORITE == p_tool) {
1203 String name = selected_favorite_root.get_slicec(' ', 0);
1204 if (ScriptServer::is_global_class(name)) {
1205 Ref<Script> scr = ResourceLoader::load(ScriptServer::get_global_class_path(name), "Script");
1206 if (scr.is_valid()) {
1207 new_node = Object::cast_to<Node>(ClassDB::instantiate(scr->get_instance_base_type()));
1208 if (new_node) {
1209 new_node->set_script(scr);
1210 new_node->set_name(name);
1211 }
1212 }
1213 } else {
1214 new_node = Object::cast_to<Node>(ClassDB::instantiate(selected_favorite_root));
1215 }
1216
1217 if (!new_node) {
1218 new_node = memnew(Node);
1219 ERR_PRINT("Creating root from favorite '" + selected_favorite_root + "' failed. Creating 'Node' instead.");
1220 }
1221 } else {
1222 switch (p_tool) {
1223 case TOOL_CREATE_2D_SCENE:
1224 new_node = memnew(Node2D);
1225 break;
1226 case TOOL_CREATE_3D_SCENE:
1227 new_node = memnew(Node3D);
1228 break;
1229 case TOOL_CREATE_USER_INTERFACE: {
1230 Control *node = memnew(Control);
1231 // Making the root control full rect by default is more useful for resizable UIs.
1232 node->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
1233 node->set_grow_direction_preset(PRESET_FULL_RECT);
1234 new_node = node;
1235
1236 } break;
1237 }
1238 }
1239
1240 add_root_node(new_node);
1241
1242 EditorNode::get_singleton()->edit_node(new_node);
1243 editor_selection->clear();
1244 editor_selection->add_node(new_node);
1245
1246 scene_tree->get_scene_tree()->grab_focus();
1247 } break;
1248
1249 default: {
1250 _filter_option_selected(p_tool);
1251
1252 if (p_tool >= EDIT_SUBRESOURCE_BASE) {
1253 int idx = p_tool - EDIT_SUBRESOURCE_BASE;
1254
1255 ERR_FAIL_INDEX(idx, subresources.size());
1256
1257 Object *obj = ObjectDB::get_instance(subresources[idx]);
1258 ERR_FAIL_NULL(obj);
1259
1260 _push_item(obj);
1261 }
1262 }
1263 }
1264}
1265
1266void SceneTreeDock::_property_selected(int p_idx) {
1267 ERR_FAIL_NULL(property_drop_node);
1268 _perform_property_drop(property_drop_node, menu_properties->get_item_metadata(p_idx), ResourceLoader::load(resource_drop_path));
1269 property_drop_node = nullptr;
1270}
1271
1272void SceneTreeDock::_perform_property_drop(Node *p_node, String p_property, Ref<Resource> p_res) {
1273 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
1274 undo_redo->create_action(vformat(TTR("Set %s"), p_property));
1275 undo_redo->add_do_property(p_node, p_property, p_res);
1276 undo_redo->add_undo_property(p_node, p_property, p_node->get(p_property));
1277 undo_redo->commit_action();
1278}
1279
1280void SceneTreeDock::add_root_node(Node *p_node) {
1281 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
1282 undo_redo->create_action_for_history(TTR("New Scene Root"), editor_data->get_current_edited_scene_history_id());
1283 undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", p_node);
1284 undo_redo->add_do_method(scene_tree, "update_tree");
1285 undo_redo->add_do_reference(p_node);
1286 undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
1287 undo_redo->commit_action();
1288}
1289
1290void SceneTreeDock::_notification(int p_what) {
1291 switch (p_what) {
1292 case NOTIFICATION_READY: {
1293 if (!first_enter) {
1294 break;
1295 }
1296 first_enter = false;
1297
1298 EditorFeatureProfileManager::get_singleton()->connect("current_feature_profile_changed", callable_mp(this, &SceneTreeDock::_feature_profile_changed));
1299
1300 CanvasItemEditorPlugin *canvas_item_plugin = Object::cast_to<CanvasItemEditorPlugin>(editor_data->get_editor_by_name("2D"));
1301 if (canvas_item_plugin) {
1302 canvas_item_plugin->get_canvas_item_editor()->connect("item_lock_status_changed", callable_mp(scene_tree, &SceneTreeEditor::_update_tree).bind(false));
1303 canvas_item_plugin->get_canvas_item_editor()->connect("item_group_status_changed", callable_mp(scene_tree, &SceneTreeEditor::_update_tree).bind(false));
1304 scene_tree->connect("node_changed", callable_mp((CanvasItem *)canvas_item_plugin->get_canvas_item_editor()->get_viewport_control(), &CanvasItem::queue_redraw));
1305 }
1306
1307 Node3DEditorPlugin *spatial_editor_plugin = Object::cast_to<Node3DEditorPlugin>(editor_data->get_editor_by_name("3D"));
1308 spatial_editor_plugin->get_spatial_editor()->connect("item_lock_status_changed", callable_mp(scene_tree, &SceneTreeEditor::_update_tree).bind(false));
1309 spatial_editor_plugin->get_spatial_editor()->connect("item_group_status_changed", callable_mp(scene_tree, &SceneTreeEditor::_update_tree).bind(false));
1310
1311 filter->set_clear_button_enabled(true);
1312
1313 // create_root_dialog
1314 HBoxContainer *top_row = memnew(HBoxContainer);
1315 top_row->set_h_size_flags(SIZE_EXPAND_FILL);
1316 Label *l = memnew(Label(TTR("Create Root Node:")));
1317 l->set_theme_type_variation("HeaderSmall");
1318 top_row->add_child(l);
1319 top_row->add_spacer();
1320
1321 node_shortcuts_toggle = memnew(Button);
1322 node_shortcuts_toggle->set_flat(true);
1323 node_shortcuts_toggle->set_icon(get_editor_theme_icon(SNAME("Favorites")));
1324 node_shortcuts_toggle->set_toggle_mode(true);
1325 node_shortcuts_toggle->set_tooltip_text(TTR("Switch to Favorite Nodes"));
1326 node_shortcuts_toggle->set_pressed(EDITOR_GET("_use_favorites_root_selection"));
1327 node_shortcuts_toggle->set_anchors_and_offsets_preset(Control::PRESET_CENTER_RIGHT);
1328 node_shortcuts_toggle->connect("pressed", callable_mp(this, &SceneTreeDock::_update_create_root_dialog));
1329 top_row->add_child(node_shortcuts_toggle);
1330
1331 create_root_dialog->add_child(top_row);
1332
1333 ScrollContainer *scroll_container = memnew(ScrollContainer);
1334 create_root_dialog->add_child(scroll_container);
1335 scroll_container->set_v_size_flags(SIZE_EXPAND_FILL);
1336 scroll_container->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
1337
1338 VBoxContainer *node_shortcuts = memnew(VBoxContainer);
1339 scroll_container->add_child(node_shortcuts);
1340 node_shortcuts->set_h_size_flags(SIZE_EXPAND_FILL);
1341
1342 beginner_node_shortcuts = memnew(VBoxContainer);
1343 node_shortcuts->add_child(beginner_node_shortcuts);
1344
1345 button_2d = memnew(Button);
1346 beginner_node_shortcuts->add_child(button_2d);
1347 button_2d->set_text(TTR("2D Scene"));
1348 button_2d->set_icon(get_editor_theme_icon(SNAME("Node2D")));
1349 button_2d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_2D_SCENE, false));
1350
1351 button_3d = memnew(Button);
1352 beginner_node_shortcuts->add_child(button_3d);
1353 button_3d->set_text(TTR("3D Scene"));
1354 button_3d->set_icon(get_editor_theme_icon(SNAME("Node3D")));
1355 button_3d->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_3D_SCENE, false));
1356
1357 button_ui = memnew(Button);
1358 beginner_node_shortcuts->add_child(button_ui);
1359 button_ui->set_text(TTR("User Interface"));
1360 button_ui->set_icon(get_editor_theme_icon(SNAME("Control")));
1361 button_ui->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_CREATE_USER_INTERFACE, false));
1362
1363 favorite_node_shortcuts = memnew(VBoxContainer);
1364 node_shortcuts->add_child(favorite_node_shortcuts);
1365
1366 button_custom = memnew(Button);
1367 node_shortcuts->add_child(button_custom);
1368 button_custom->set_text(TTR("Other Node"));
1369 button_custom->set_icon(get_editor_theme_icon(SNAME("Add")));
1370 button_custom->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_NEW, false));
1371
1372 button_clipboard = memnew(Button);
1373 node_shortcuts->add_child(button_clipboard);
1374 button_clipboard->set_text(TTR("Paste From Clipboard"));
1375 button_clipboard->set_icon(get_editor_theme_icon(SNAME("ActionPaste")));
1376 button_clipboard->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_PASTE, false));
1377
1378 _update_create_root_dialog();
1379 } break;
1380
1381 case NOTIFICATION_ENTER_TREE: {
1382 clear_inherit_confirm->connect("confirmed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM, false));
1383 scene_tree->set_auto_expand_selected(EDITOR_GET("docks/scene_tree/auto_expand_to_selected"), false);
1384 } break;
1385
1386 case NOTIFICATION_EXIT_TREE: {
1387 clear_inherit_confirm->disconnect("confirmed", callable_mp(this, &SceneTreeDock::_tool_selected));
1388 } break;
1389
1390 case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
1391 scene_tree->set_auto_expand_selected(EDITOR_GET("docks/scene_tree/auto_expand_to_selected"), false);
1392 } break;
1393
1394 case NOTIFICATION_THEME_CHANGED: {
1395 button_add->set_icon(get_editor_theme_icon(SNAME("Add")));
1396 button_instance->set_icon(get_editor_theme_icon(SNAME("Instance")));
1397 button_create_script->set_icon(get_editor_theme_icon(SNAME("ScriptCreate")));
1398 button_detach_script->set_icon(get_editor_theme_icon(SNAME("ScriptRemove")));
1399 button_tree_menu->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl")));
1400
1401 filter->set_right_icon(get_editor_theme_icon(SNAME("Search")));
1402
1403 PopupMenu *filter_menu = filter->get_menu();
1404 filter_menu->set_item_icon(filter_menu->get_item_idx_from_text(TTR("Filters")), get_editor_theme_icon(SNAME("Search")));
1405 filter_menu->set_item_icon(filter_menu->get_item_index(FILTER_BY_TYPE), get_editor_theme_icon(SNAME("Node")));
1406 filter_menu->set_item_icon(filter_menu->get_item_index(FILTER_BY_GROUP), get_editor_theme_icon(SNAME("Groups")));
1407
1408 // These buttons are created on READY, because reasons...
1409 if (button_2d) {
1410 button_2d->set_icon(get_editor_theme_icon(SNAME("Node2D")));
1411 }
1412 if (button_3d) {
1413 button_3d->set_icon(get_editor_theme_icon(SNAME("Node3D")));
1414 }
1415 if (button_ui) {
1416 button_ui->set_icon(get_editor_theme_icon(SNAME("Control")));
1417 }
1418 if (button_custom) {
1419 button_custom->set_icon(get_editor_theme_icon(SNAME("Add")));
1420 }
1421 if (button_clipboard) {
1422 button_clipboard->set_icon(get_editor_theme_icon(SNAME("ActionPaste")));
1423 }
1424
1425 menu_subresources->add_theme_constant_override("icon_max_width", get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor)));
1426 } break;
1427
1428 case NOTIFICATION_PROCESS: {
1429 bool show_create_root = bool(EDITOR_GET("interface/editors/show_scene_tree_root_selection")) && get_tree()->get_edited_scene_root() == nullptr;
1430
1431 if (show_create_root != create_root_dialog->is_visible_in_tree() && !remote_tree->is_visible()) {
1432 if (show_create_root) {
1433 create_root_dialog->show();
1434 scene_tree->hide();
1435 } else {
1436 create_root_dialog->hide();
1437 scene_tree->show();
1438 }
1439 }
1440 } break;
1441 }
1442}
1443
1444void SceneTreeDock::_node_replace_owner(Node *p_base, Node *p_node, Node *p_root, ReplaceOwnerMode p_mode) {
1445 if (p_node->get_owner() == p_base && p_node != p_root) {
1446 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
1447 switch (p_mode) {
1448 case MODE_BIDI: {
1449 bool disable_unique = p_node->is_unique_name_in_owner() && p_root->get_node_or_null(UNIQUE_NODE_PREFIX + String(p_node->get_name())) != nullptr;
1450 if (disable_unique) {
1451 // Will create a unique name conflict. Disable before setting owner.
1452 undo_redo->add_do_method(p_node, "set_unique_name_in_owner", false);
1453 }
1454 undo_redo->add_do_method(p_node, "set_owner", p_root);
1455 undo_redo->add_undo_method(p_node, "set_owner", p_base);
1456 if (disable_unique) {
1457 // Will create a unique name conflict. Enable after setting owner.
1458 undo_redo->add_undo_method(p_node, "set_unique_name_in_owner", true);
1459 }
1460
1461 } break;
1462 case MODE_DO: {
1463 undo_redo->add_do_method(p_node, "set_owner", p_root);
1464
1465 } break;
1466 case MODE_UNDO: {
1467 undo_redo->add_undo_method(p_node, "set_owner", p_root);
1468
1469 } break;
1470 }
1471 }
1472
1473 for (int i = 0; i < p_node->get_child_count(); i++) {
1474 _node_replace_owner(p_base, p_node->get_child(i), p_root, p_mode);
1475 }
1476}
1477
1478void SceneTreeDock::_load_request(const String &p_path) {
1479 EditorNode::get_singleton()->open_request(p_path);
1480 _local_tree_selected();
1481}
1482
1483void SceneTreeDock::_script_open_request(const Ref<Script> &p_script) {
1484 EditorNode::get_singleton()->edit_resource(p_script);
1485}
1486
1487void SceneTreeDock::_push_item(Object *p_object) {
1488 Node *node = Object::cast_to<Node>(p_object);
1489 if (node || !p_object) {
1490 // Assume that null object is a Node.
1491 EditorNode::get_singleton()->push_node_item(node);
1492 } else {
1493 EditorNode::get_singleton()->push_item(p_object);
1494 }
1495
1496 if (p_object == nullptr) {
1497 EditorNode::get_singleton()->hide_unused_editors(this);
1498 }
1499}
1500
1501void SceneTreeDock::_handle_select(Node *p_node) {
1502 if (tree_clicked) {
1503 pending_click_select = p_node;
1504 } else {
1505 _push_item(p_node);
1506 }
1507}
1508
1509void SceneTreeDock::_node_selected() {
1510 Node *node = scene_tree->get_selected();
1511
1512 if (!node) {
1513 return;
1514 }
1515 _handle_select(node);
1516}
1517
1518void SceneTreeDock::_node_renamed() {
1519 _node_selected();
1520}
1521
1522void SceneTreeDock::_set_owners(Node *p_owner, const Array &p_nodes) {
1523 for (int i = 0; i < p_nodes.size(); i++) {
1524 Node *n = Object::cast_to<Node>(p_nodes[i]);
1525 if (!n) {
1526 continue;
1527 }
1528 n->set_owner(p_owner);
1529 }
1530}
1531
1532void SceneTreeDock::_fill_path_renames(Vector<StringName> base_path, Vector<StringName> new_base_path, Node *p_node, HashMap<Node *, NodePath> *p_renames) {
1533 base_path.push_back(p_node->get_name());
1534
1535 NodePath new_path;
1536 if (!new_base_path.is_empty()) {
1537 new_base_path.push_back(p_node->get_name());
1538 new_path = NodePath(new_base_path, true);
1539 }
1540
1541 p_renames->insert(p_node, new_path);
1542
1543 for (int i = 0; i < p_node->get_child_count(); i++) {
1544 _fill_path_renames(base_path, new_base_path, p_node->get_child(i), p_renames);
1545 }
1546}
1547
1548bool SceneTreeDock::_has_tracks_to_delete(Node *p_node, List<Node *> &p_to_delete) const {
1549 AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
1550 if (ap) {
1551 Node *root = ap->get_node(ap->get_root());
1552 if (root && !p_to_delete.find(root)) {
1553 List<StringName> anims;
1554 ap->get_animation_list(&anims);
1555
1556 for (const StringName &E : anims) {
1557 Ref<Animation> anim = ap->get_animation(E);
1558 if (anim.is_null()) {
1559 continue;
1560 }
1561
1562 for (int i = 0; i < anim->get_track_count(); i++) {
1563 NodePath track_np = anim->track_get_path(i);
1564 Node *n = root->get_node_or_null(track_np);
1565 if (n) {
1566 for (const Node *F : p_to_delete) {
1567 if (F == n || F->is_ancestor_of(n)) {
1568 return true;
1569 }
1570 }
1571 }
1572 }
1573 }
1574 }
1575 }
1576
1577 for (int i = 0; i < p_node->get_child_count(); i++) {
1578 if (_has_tracks_to_delete(p_node->get_child(i), p_to_delete)) {
1579 return true;
1580 }
1581 }
1582 return false;
1583}
1584
1585void SceneTreeDock::fill_path_renames(Node *p_node, Node *p_new_parent, HashMap<Node *, NodePath> *p_renames) {
1586 Vector<StringName> base_path;
1587 Node *n = p_node->get_parent();
1588 while (n) {
1589 base_path.push_back(n->get_name());
1590 n = n->get_parent();
1591 }
1592 base_path.reverse();
1593
1594 Vector<StringName> new_base_path;
1595 if (p_new_parent) {
1596 n = p_new_parent;
1597 while (n) {
1598 new_base_path.push_back(n->get_name());
1599 n = n->get_parent();
1600 }
1601
1602 new_base_path.reverse();
1603 }
1604
1605 _fill_path_renames(base_path, new_base_path, p_node, p_renames);
1606}
1607
1608bool SceneTreeDock::_update_node_path(Node *p_root_node, NodePath &r_node_path, HashMap<Node *, NodePath> *p_renames) const {
1609 Node *target_node = p_root_node->get_node_or_null(r_node_path);
1610 ERR_FAIL_NULL_V_MSG(target_node, false, "Found invalid node path '" + String(r_node_path) + "' on node '" + String(scene_root->get_path_to(p_root_node)) + "'");
1611
1612 // Try to find the target node in modified node paths.
1613 HashMap<Node *, NodePath>::Iterator found_node_path = p_renames->find(target_node);
1614 if (found_node_path) {
1615 HashMap<Node *, NodePath>::Iterator found_root_path = p_renames->find(p_root_node);
1616 NodePath root_path_new = found_root_path ? found_root_path->value : p_root_node->get_path();
1617 r_node_path = root_path_new.rel_path_to(found_node_path->value);
1618
1619 return true;
1620 }
1621
1622 // Update the path if the base node has changed and has not been deleted.
1623 HashMap<Node *, NodePath>::Iterator found_root_path = p_renames->find(p_root_node);
1624 if (found_root_path) {
1625 NodePath root_path_new = found_root_path->value;
1626 if (!root_path_new.is_empty()) {
1627 NodePath old_abs_path = NodePath(String(p_root_node->get_path()).path_join(r_node_path));
1628 old_abs_path.simplify();
1629 r_node_path = root_path_new.rel_path_to(old_abs_path);
1630 }
1631
1632 return true;
1633 }
1634
1635 return false;
1636}
1637
1638bool SceneTreeDock::_check_node_path_recursive(Node *p_root_node, Variant &r_variant, HashMap<Node *, NodePath> *p_renames) const {
1639 switch (r_variant.get_type()) {
1640 case Variant::NODE_PATH: {
1641 NodePath node_path = r_variant;
1642 if (!node_path.is_empty() && _update_node_path(p_root_node, node_path, p_renames)) {
1643 r_variant = node_path;
1644 return true;
1645 }
1646 } break;
1647
1648 case Variant::ARRAY: {
1649 Array a = r_variant;
1650 bool updated = false;
1651 for (int i = 0; i < a.size(); i++) {
1652 Variant value = a[i];
1653 if (_check_node_path_recursive(p_root_node, value, p_renames)) {
1654 if (!updated) {
1655 a = a.duplicate(); // Need to duplicate for undo-redo to work.
1656 updated = true;
1657 }
1658 a[i] = value;
1659 }
1660 }
1661 if (updated) {
1662 r_variant = a;
1663 return true;
1664 }
1665 } break;
1666
1667 case Variant::DICTIONARY: {
1668 Dictionary d = r_variant;
1669 bool updated = false;
1670 for (int i = 0; i < d.size(); i++) {
1671 Variant value = d.get_value_at_index(i);
1672 if (_check_node_path_recursive(p_root_node, value, p_renames)) {
1673 if (!updated) {
1674 d = d.duplicate(); // Need to duplicate for undo-redo to work.
1675 updated = true;
1676 }
1677 d[d.get_key_at_index(i)] = value;
1678 }
1679 }
1680 if (updated) {
1681 r_variant = d;
1682 return true;
1683 }
1684 } break;
1685
1686 default: {
1687 }
1688 }
1689
1690 return false;
1691}
1692
1693void SceneTreeDock::perform_node_renames(Node *p_base, HashMap<Node *, NodePath> *p_renames, HashMap<Ref<Animation>, HashSet<int>> *r_rem_anims) {
1694 HashMap<Ref<Animation>, HashSet<int>> rem_anims;
1695 if (!r_rem_anims) {
1696 r_rem_anims = &rem_anims;
1697 }
1698
1699 if (!p_base) {
1700 p_base = edited_scene;
1701 }
1702
1703 if (!p_base) {
1704 return;
1705 }
1706
1707 // No renaming if base node is deleted.
1708 HashMap<Node *, NodePath>::Iterator found_base_path = p_renames->find(p_base);
1709 if (found_base_path && found_base_path->value.is_empty()) {
1710 return;
1711 }
1712
1713 // Renaming node paths used in node properties.
1714 List<PropertyInfo> properties;
1715 p_base->get_property_list(&properties);
1716
1717 for (const PropertyInfo &E : properties) {
1718 if (!(E.usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR))) {
1719 continue;
1720 }
1721 String propertyname = E.name;
1722 Variant old_variant = p_base->get(propertyname);
1723 Variant updated_variant = old_variant;
1724 if (_check_node_path_recursive(p_base, updated_variant, p_renames)) {
1725 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
1726 undo_redo->add_do_property(p_base, propertyname, updated_variant);
1727 undo_redo->add_undo_property(p_base, propertyname, old_variant);
1728 p_base->set(propertyname, updated_variant);
1729 }
1730 }
1731
1732 bool autorename_animation_tracks = bool(EDITOR_GET("editors/animation/autorename_animation_tracks"));
1733
1734 if (autorename_animation_tracks && Object::cast_to<AnimationPlayer>(p_base)) {
1735 AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_base);
1736 List<StringName> anims;
1737 ap->get_animation_list(&anims);
1738 Node *root = ap->get_node(ap->get_root());
1739
1740 if (root) {
1741 HashMap<Node *, NodePath>::Iterator found_root_path = p_renames->find(root);
1742 NodePath new_root_path = found_root_path ? found_root_path->value : root->get_path();
1743 if (!new_root_path.is_empty()) { // No renaming if root node is deleted.
1744 for (const StringName &E : anims) {
1745 Ref<Animation> anim = ap->get_animation(E);
1746 if (!r_rem_anims->has(anim)) {
1747 r_rem_anims->insert(anim, HashSet<int>());
1748 HashSet<int> &ran = r_rem_anims->find(anim)->value;
1749 for (int i = 0; i < anim->get_track_count(); i++) {
1750 ran.insert(i);
1751 }
1752 }
1753
1754 HashSet<int> &ran = r_rem_anims->find(anim)->value;
1755
1756 if (anim.is_null()) {
1757 continue;
1758 }
1759
1760 int tracks_removed = 0;
1761
1762 for (int i = 0; i < anim->get_track_count(); i++) {
1763 NodePath track_np = anim->track_get_path(i);
1764 Node *n = root->get_node_or_null(track_np);
1765 if (!n) {
1766 continue;
1767 }
1768
1769 if (!ran.has(i)) {
1770 continue; //channel was removed
1771 }
1772
1773 HashMap<Node *, NodePath>::Iterator found_path = p_renames->find(n);
1774 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
1775 if (found_path) {
1776 if (found_path->value.is_empty()) {
1777 //will be erased
1778
1779 int idx = i - tracks_removed;
1780 tracks_removed++;
1781
1782 undo_redo->add_do_method(anim.ptr(), "remove_track", idx);
1783 undo_redo->add_undo_method(anim.ptr(), "add_track", anim->track_get_type(i), idx);
1784 undo_redo->add_undo_method(anim.ptr(), "track_set_path", idx, track_np);
1785 undo_redo->add_undo_method(anim.ptr(), "track_set_interpolation_type", idx, anim->track_get_interpolation_type(i));
1786 for (int j = 0; j < anim->track_get_key_count(i); j++) {
1787 undo_redo->add_undo_method(anim.ptr(), "track_insert_key", idx, anim->track_get_key_time(i, j), anim->track_get_key_value(i, j), anim->track_get_key_transition(i, j));
1788 }
1789
1790 ran.erase(i); //byebye channel
1791
1792 } else {
1793 //will be renamed
1794 NodePath rel_path = new_root_path.rel_path_to(found_path->value);
1795
1796 NodePath new_path = NodePath(rel_path.get_names(), track_np.get_subnames(), false);
1797 if (new_path == track_np) {
1798 continue; //bleh
1799 }
1800 undo_redo->add_do_method(anim.ptr(), "track_set_path", i, new_path);
1801 undo_redo->add_undo_method(anim.ptr(), "track_set_path", i, track_np);
1802 }
1803 }
1804 }
1805 }
1806 }
1807 }
1808 }
1809
1810 for (int i = 0; i < p_base->get_child_count(); i++) {
1811 perform_node_renames(p_base->get_child(i), p_renames, r_rem_anims);
1812 }
1813}
1814
1815void SceneTreeDock::_node_prerenamed(Node *p_node, const String &p_new_name) {
1816 HashMap<Node *, NodePath> path_renames;
1817
1818 Vector<StringName> base_path;
1819 Node *n = p_node->get_parent();
1820 while (n) {
1821 base_path.push_back(n->get_name());
1822 n = n->get_parent();
1823 }
1824 base_path.reverse();
1825
1826 Vector<StringName> new_base_path = base_path;
1827 base_path.push_back(p_node->get_name());
1828
1829 new_base_path.push_back(p_new_name);
1830
1831 NodePath new_path(new_base_path, true);
1832 path_renames[p_node] = new_path;
1833
1834 for (int i = 0; i < p_node->get_child_count(); i++) {
1835 _fill_path_renames(base_path, new_base_path, p_node->get_child(i), &path_renames);
1836 }
1837
1838 perform_node_renames(nullptr, &path_renames);
1839}
1840
1841bool SceneTreeDock::_validate_no_foreign() {
1842 List<Node *> selection = editor_selection->get_selected_node_list();
1843
1844 for (Node *E : selection) {
1845 if (E != edited_scene && E->get_owner() != edited_scene) {
1846 accept->set_text(TTR("Can't operate on nodes from a foreign scene!"));
1847 accept->popup_centered();
1848 return false;
1849 }
1850
1851 // When edited_scene inherits from another one the root Node will be the parent Scene,
1852 // we don't want to consider that Node a foreign one otherwise we would not be able to
1853 // delete it.
1854 if (edited_scene->get_scene_inherited_state().is_valid() && edited_scene == E) {
1855 continue;
1856 }
1857
1858 if (edited_scene->get_scene_inherited_state().is_valid() && edited_scene->get_scene_inherited_state()->find_node_by_path(edited_scene->get_path_to(E)) >= 0) {
1859 accept->set_text(TTR("Can't operate on nodes the current scene inherits from!"));
1860 accept->popup_centered();
1861 return false;
1862 }
1863 }
1864
1865 return true;
1866}
1867
1868bool SceneTreeDock::_validate_no_instance() {
1869 List<Node *> selection = editor_selection->get_selected_node_list();
1870
1871 for (Node *E : selection) {
1872 if (E != edited_scene && !E->get_scene_file_path().is_empty()) {
1873 accept->set_text(TTR("This operation can't be done on instantiated scenes."));
1874 accept->popup_centered();
1875 return false;
1876 }
1877 }
1878
1879 return true;
1880}
1881
1882void SceneTreeDock::_node_reparent(NodePath p_path, bool p_keep_global_xform) {
1883 Node *new_parent = scene_root->get_node(p_path);
1884 ERR_FAIL_NULL(new_parent);
1885
1886 List<Node *> selection = editor_selection->get_selected_node_list();
1887
1888 if (selection.is_empty()) {
1889 return; // Nothing to reparent.
1890 }
1891
1892 Vector<Node *> nodes;
1893
1894 for (Node *E : selection) {
1895 nodes.push_back(E);
1896 }
1897
1898 _do_reparent(new_parent, -1, nodes, p_keep_global_xform);
1899}
1900
1901void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, Vector<Node *> p_nodes, bool p_keep_global_xform) {
1902 Node *new_parent = p_new_parent;
1903 ERR_FAIL_NULL(new_parent);
1904
1905 if (p_nodes.size() == 0) {
1906 return; // Nothing to reparent.
1907 }
1908
1909 p_nodes.sort_custom<Node::Comparator>(); //Makes result reliable.
1910
1911 bool no_change = true;
1912 for (int ni = 0; ni < p_nodes.size(); ni++) {
1913 if (p_nodes[ni] == p_new_parent) {
1914 return; // Attempt to reparent to itself.
1915 }
1916 // `move_child` + `get_index` doesn't really work for internal nodes.
1917 ERR_FAIL_COND_MSG(p_nodes[ni]->get_internal_mode() != INTERNAL_MODE_DISABLED, "Trying to move internal node, this is not supported.");
1918
1919 if (p_nodes[ni]->get_parent() != p_new_parent || p_position_in_parent + ni != p_nodes[ni]->get_index(false)) {
1920 no_change = false;
1921 }
1922 }
1923
1924 if (no_change) {
1925 return; // Position and parent didn't change.
1926 }
1927
1928 Node *validate = new_parent;
1929 while (validate) {
1930 ERR_FAIL_COND_MSG(p_nodes.has(validate), "Selection changed at some point. Can't reparent.");
1931 validate = validate->get_parent();
1932 }
1933
1934 // Sort by tree order, so re-adding is easy.
1935 p_nodes.sort_custom<Node::Comparator>();
1936
1937 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
1938 undo_redo->create_action(TTR("Reparent Node"), UndoRedo::MERGE_DISABLE, p_nodes[0]);
1939
1940 HashMap<Node *, NodePath> path_renames;
1941 Vector<StringName> former_names;
1942
1943 int inc = 0;
1944
1945 for (int ni = 0; ni < p_nodes.size(); ni++) {
1946 // No undo implemented for this yet.
1947 Node *node = p_nodes[ni];
1948
1949 fill_path_renames(node, new_parent, &path_renames);
1950 former_names.push_back(node->get_name());
1951
1952 List<Node *> owned;
1953 node->get_owned_by(node->get_owner(), &owned);
1954 Array owners;
1955 for (Node *E : owned) {
1956 owners.push_back(E);
1957 }
1958
1959 bool same_parent = new_parent == node->get_parent();
1960 if (same_parent && node->get_index(false) < p_position_in_parent + ni) {
1961 inc--; // If the child will generate a gap when moved, adjust.
1962 }
1963
1964 if (!same_parent) {
1965 undo_redo->add_do_method(node->get_parent(), "remove_child", node);
1966 undo_redo->add_do_method(new_parent, "add_child", node, true);
1967 }
1968
1969 int new_position_in_parent = p_position_in_parent == -1 ? -1 : p_position_in_parent + inc;
1970 if (new_position_in_parent >= 0 || same_parent) {
1971 undo_redo->add_do_method(new_parent, "move_child", node, new_position_in_parent);
1972 }
1973
1974 EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
1975 String old_name = former_names[ni];
1976 String new_name = new_parent->validate_child_name(node);
1977
1978 // Name was modified, fix the path renames.
1979 if (old_name.casecmp_to(new_name) != 0) {
1980 // Fix the to name to have the new name.
1981 HashMap<Node *, NodePath>::Iterator found_path = path_renames.find(node);
1982 if (found_path) {
1983 NodePath old_new_name = found_path->value;
1984
1985 Vector<StringName> unfixed_new_names = old_new_name.get_names();
1986 Vector<StringName> fixed_new_names;
1987
1988 // Get last name and replace with fixed new name.
1989 for (int a = 0; a < (unfixed_new_names.size() - 1); a++) {
1990 fixed_new_names.push_back(unfixed_new_names[a]);
1991 }
1992 fixed_new_names.push_back(new_name);
1993
1994 NodePath fixed_node_path = NodePath(fixed_new_names, true);
1995 path_renames[node] = fixed_node_path;
1996 } else {
1997 ERR_PRINT("Internal error. Can't find renamed path for node '" + node->get_path() + "'");
1998 }
1999 }
2000
2001 undo_redo->add_do_method(ed, "live_debug_reparent_node", edited_scene->get_path_to(node), edited_scene->get_path_to(new_parent), new_name, new_position_in_parent);
2002 undo_redo->add_undo_method(ed, "live_debug_reparent_node", NodePath(String(edited_scene->get_path_to(new_parent)).path_join(new_name)), edited_scene->get_path_to(node->get_parent()), node->get_name(), node->get_index(false));
2003
2004 if (p_keep_global_xform) {
2005 if (Object::cast_to<Node2D>(node)) {
2006 undo_redo->add_do_method(node, "set_global_transform", Object::cast_to<Node2D>(node)->get_global_transform());
2007 }
2008 if (Object::cast_to<Node3D>(node)) {
2009 undo_redo->add_do_method(node, "set_global_transform", Object::cast_to<Node3D>(node)->get_global_transform());
2010 }
2011 if (Object::cast_to<Control>(node)) {
2012 undo_redo->add_do_method(node, "set_global_position", Object::cast_to<Control>(node)->get_global_position());
2013 }
2014 }
2015
2016 undo_redo->add_do_method(this, "_set_owners", edited_scene, owners);
2017
2018 if (AnimationPlayerEditor::get_singleton()->get_track_editor()->get_root() == node) {
2019 undo_redo->add_do_method(AnimationPlayerEditor::get_singleton()->get_track_editor(), "set_root", node);
2020 }
2021
2022 undo_redo->add_undo_method(new_parent, "remove_child", node);
2023 undo_redo->add_undo_method(node, "set_name", former_names[ni]);
2024
2025 inc++;
2026 }
2027
2028 // Add and move in a second step (so old order is preserved).
2029 for (int ni = 0; ni < p_nodes.size(); ni++) {
2030 Node *node = p_nodes[ni];
2031
2032 List<Node *> owned;
2033 node->get_owned_by(node->get_owner(), &owned);
2034 Array owners;
2035 for (Node *E : owned) {
2036 owners.push_back(E);
2037 }
2038
2039 int child_pos = node->get_index(false);
2040
2041 undo_redo->add_undo_method(node->get_parent(), "add_child", node, true);
2042 undo_redo->add_undo_method(node->get_parent(), "move_child", node, child_pos);
2043 undo_redo->add_undo_method(this, "_set_owners", edited_scene, owners);
2044 if (AnimationPlayerEditor::get_singleton()->get_track_editor()->get_root() == node) {
2045 undo_redo->add_undo_method(AnimationPlayerEditor::get_singleton()->get_track_editor(), "set_root", node);
2046 }
2047
2048 if (p_keep_global_xform) {
2049 if (Object::cast_to<Node2D>(node)) {
2050 undo_redo->add_undo_method(node, "set_transform", Object::cast_to<Node2D>(node)->get_transform());
2051 }
2052 if (Object::cast_to<Node3D>(node)) {
2053 undo_redo->add_undo_method(node, "set_transform", Object::cast_to<Node3D>(node)->get_transform());
2054 }
2055 if (Object::cast_to<Control>(node)) {
2056 undo_redo->add_undo_method(node, "set_position", Object::cast_to<Control>(node)->get_position());
2057 }
2058 }
2059 }
2060
2061 perform_node_renames(nullptr, &path_renames);
2062
2063 undo_redo->commit_action();
2064}
2065
2066void SceneTreeDock::_script_created(Ref<Script> p_script) {
2067 List<Node *> selected = editor_selection->get_selected_node_list();
2068
2069 if (selected.is_empty()) {
2070 return;
2071 }
2072
2073 if (p_script->is_built_in()) {
2074 p_script->set_path(edited_scene->get_scene_file_path() + "::");
2075 }
2076
2077 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2078 undo_redo->create_action(TTR("Attach Script"), UndoRedo::MERGE_DISABLE, selected.front()->get());
2079 for (Node *E : selected) {
2080 Ref<Script> existing = E->get_script();
2081 undo_redo->add_do_method(InspectorDock::get_singleton(), "store_script_properties", E);
2082 undo_redo->add_undo_method(InspectorDock::get_singleton(), "store_script_properties", E);
2083 undo_redo->add_do_method(E, "set_script", p_script);
2084 undo_redo->add_undo_method(E, "set_script", existing);
2085 undo_redo->add_do_method(InspectorDock::get_singleton(), "apply_script_properties", E);
2086 undo_redo->add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", E);
2087 undo_redo->add_do_method(this, "_update_script_button");
2088 undo_redo->add_undo_method(this, "_update_script_button");
2089 }
2090 undo_redo->commit_action();
2091
2092 _push_item(p_script.ptr());
2093 _update_script_button();
2094}
2095
2096void SceneTreeDock::_shader_created(Ref<Shader> p_shader) {
2097 if (selected_shader_material.is_null()) {
2098 return;
2099 }
2100
2101 Ref<Shader> existing = selected_shader_material->get_shader();
2102
2103 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2104 undo_redo->create_action(TTR("Set Shader"));
2105 undo_redo->add_do_method(selected_shader_material.ptr(), "set_shader", p_shader);
2106 undo_redo->add_undo_method(selected_shader_material.ptr(), "set_shader", existing);
2107 undo_redo->commit_action();
2108}
2109
2110void SceneTreeDock::_script_creation_closed() {
2111 script_create_dialog->disconnect("script_created", callable_mp(this, &SceneTreeDock::_script_created));
2112 script_create_dialog->disconnect("confirmed", callable_mp(this, &SceneTreeDock::_script_creation_closed));
2113 script_create_dialog->disconnect("canceled", callable_mp(this, &SceneTreeDock::_script_creation_closed));
2114}
2115
2116void SceneTreeDock::_shader_creation_closed() {
2117 shader_create_dialog->disconnect("shader_created", callable_mp(this, &SceneTreeDock::_shader_created));
2118 shader_create_dialog->disconnect("confirmed", callable_mp(this, &SceneTreeDock::_shader_creation_closed));
2119 shader_create_dialog->disconnect("canceled", callable_mp(this, &SceneTreeDock::_shader_creation_closed));
2120}
2121
2122void SceneTreeDock::_toggle_editable_children_from_selection() {
2123 List<Node *> selection = editor_selection->get_selected_node_list();
2124 List<Node *>::Element *e = selection.front();
2125
2126 if (e) {
2127 _toggle_editable_children(e->get());
2128 }
2129}
2130
2131void SceneTreeDock::_toggle_placeholder_from_selection() {
2132 List<Node *> selection = editor_selection->get_selected_node_list();
2133 List<Node *>::Element *e = selection.front();
2134
2135 if (e) {
2136 Node *node = e->get();
2137 if (node) {
2138 _toggle_editable_children(node);
2139
2140 bool placeholder = node->get_scene_instance_load_placeholder();
2141 placeholder = !placeholder;
2142
2143 node->set_scene_instance_load_placeholder(placeholder);
2144 scene_tree->update_tree();
2145 }
2146 }
2147}
2148
2149void SceneTreeDock::_toggle_editable_children(Node *p_node) {
2150 if (p_node) {
2151 bool editable = !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node);
2152 EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(p_node, editable);
2153 if (editable) {
2154 p_node->set_scene_instance_load_placeholder(false);
2155 }
2156
2157 Node3DEditor::get_singleton()->update_all_gizmos(p_node);
2158
2159 scene_tree->update_tree();
2160 }
2161}
2162
2163void SceneTreeDock::_delete_confirm(bool p_cut) {
2164 List<Node *> remove_list = editor_selection->get_selected_node_list();
2165
2166 if (remove_list.is_empty()) {
2167 return;
2168 }
2169
2170 bool entire_scene = false;
2171
2172 for (const Node *E : remove_list) {
2173 if (E == edited_scene) {
2174 entire_scene = true;
2175 break;
2176 }
2177 }
2178
2179 EditorNode::get_singleton()->hide_unused_editors(this);
2180
2181 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2182 undo_redo->create_action(p_cut ? TTR("Cut Node(s)") : TTR("Remove Node(s)"), UndoRedo::MERGE_DISABLE, remove_list.front()->get());
2183
2184 if (entire_scene) {
2185 undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
2186 undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", edited_scene);
2187 undo_redo->add_undo_method(edited_scene, "set_owner", edited_scene->get_owner());
2188 undo_redo->add_undo_method(scene_tree, "update_tree");
2189 undo_redo->add_undo_reference(edited_scene);
2190 } else {
2191 for (const Node *E : remove_list) {
2192 // `move_child` + `get_index` doesn't really work for internal nodes.
2193 ERR_FAIL_COND_MSG(E->get_internal_mode() != INTERNAL_MODE_DISABLED, "Trying to remove internal node, this is not supported.");
2194 }
2195 if (delete_tracks_checkbox->is_pressed() || p_cut) {
2196 remove_list.sort_custom<Node::Comparator>(); // Sort nodes to keep positions.
2197 HashMap<Node *, NodePath> path_renames;
2198
2199 //delete from animation
2200 for (Node *n : remove_list) {
2201 if (!n->is_inside_tree() || !n->get_parent()) {
2202 continue;
2203 }
2204
2205 fill_path_renames(n, nullptr, &path_renames);
2206 }
2207
2208 perform_node_renames(nullptr, &path_renames);
2209 }
2210
2211 //delete for read
2212 for (Node *n : remove_list) {
2213 if (!n->is_inside_tree() || !n->get_parent()) {
2214 continue;
2215 }
2216
2217 List<Node *> owned;
2218 n->get_owned_by(n->get_owner(), &owned);
2219 Array owners;
2220 for (Node *F : owned) {
2221 owners.push_back(F);
2222 }
2223
2224 undo_redo->add_do_method(n->get_parent(), "remove_child", n);
2225 undo_redo->add_undo_method(n->get_parent(), "add_child", n, true);
2226 undo_redo->add_undo_method(n->get_parent(), "move_child", n, n->get_index(false));
2227 if (AnimationPlayerEditor::get_singleton()->get_track_editor()->get_root() == n) {
2228 undo_redo->add_undo_method(AnimationPlayerEditor::get_singleton()->get_track_editor(), "set_root", n);
2229 }
2230 undo_redo->add_undo_method(this, "_set_owners", edited_scene, owners);
2231 undo_redo->add_undo_reference(n);
2232
2233 EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
2234 undo_redo->add_do_method(ed, "live_debug_remove_and_keep_node", edited_scene->get_path_to(n), n->get_instance_id());
2235 undo_redo->add_undo_method(ed, "live_debug_restore_node", n->get_instance_id(), edited_scene->get_path_to(n->get_parent()), n->get_index(false));
2236 }
2237 }
2238 undo_redo->commit_action();
2239
2240 // hack, force 2d editor viewport to refresh after deletion
2241 if (CanvasItemEditor *editor = CanvasItemEditor::get_singleton()) {
2242 editor->get_viewport_control()->queue_redraw();
2243 }
2244
2245 _push_item(nullptr);
2246
2247 // Fixes the EditorSelectionHistory from still offering deleted notes
2248 EditorSelectionHistory *editor_history = EditorNode::get_singleton()->get_editor_selection_history();
2249 editor_history->cleanup_history();
2250 InspectorDock::get_singleton()->call("_prepare_history");
2251}
2252
2253void SceneTreeDock::_update_script_button() {
2254 if (!profile_allow_script_editing) {
2255 button_create_script->hide();
2256 button_detach_script->hide();
2257 } else if (editor_selection->get_selection().size() == 0) {
2258 button_create_script->hide();
2259 button_detach_script->hide();
2260 } else if (editor_selection->get_selection().size() == 1) {
2261 Node *n = editor_selection->get_selected_node_list()[0];
2262 if (n->get_script().is_null()) {
2263 button_create_script->show();
2264 button_detach_script->hide();
2265 } else {
2266 button_create_script->hide();
2267 button_detach_script->show();
2268 }
2269 } else {
2270 button_create_script->hide();
2271 Array selection = editor_selection->get_selected_nodes();
2272 for (int i = 0; i < selection.size(); i++) {
2273 Node *n = Object::cast_to<Node>(selection[i]);
2274 if (!n->get_script().is_null()) {
2275 button_detach_script->show();
2276 return;
2277 }
2278 }
2279 button_detach_script->hide();
2280 }
2281}
2282
2283void SceneTreeDock::_selection_changed() {
2284 int selection_size = editor_selection->get_selection().size();
2285 if (selection_size > 1) {
2286 //automatically turn on multi-edit
2287 _tool_selected(TOOL_MULTI_EDIT);
2288 } else if (selection_size == 1) {
2289 _handle_select(editor_selection->get_selection().begin()->key);
2290 } else if (selection_size == 0) {
2291 _push_item(nullptr);
2292 }
2293
2294 _update_script_button();
2295}
2296
2297void SceneTreeDock::_do_create(Node *p_parent) {
2298 Variant c = create_dialog->instantiate_selected();
2299 Node *child = Object::cast_to<Node>(c);
2300 ERR_FAIL_NULL(child);
2301
2302 String new_name = p_parent->validate_child_name(child);
2303 if (GLOBAL_GET("editor/naming/node_name_casing").operator int() != NAME_CASING_PASCAL_CASE) {
2304 new_name = adjust_name_casing(new_name);
2305 }
2306 child->set_name(new_name);
2307
2308 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2309 undo_redo->create_action_for_history(TTR("Create Node"), editor_data->get_current_edited_scene_history_id());
2310
2311 if (edited_scene) {
2312 undo_redo->add_do_method(p_parent, "add_child", child, true);
2313 undo_redo->add_do_method(child, "set_owner", edited_scene);
2314 undo_redo->add_do_method(editor_selection, "clear");
2315 undo_redo->add_do_method(editor_selection, "add_node", child);
2316 undo_redo->add_do_reference(child);
2317 undo_redo->add_undo_method(p_parent, "remove_child", child);
2318
2319 EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
2320 undo_redo->add_do_method(ed, "live_debug_create_node", edited_scene->get_path_to(p_parent), child->get_class(), new_name);
2321 undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(p_parent)).path_join(new_name)));
2322
2323 } else {
2324 undo_redo->add_do_method(EditorNode::get_singleton(), "set_edited_scene", child);
2325 undo_redo->add_do_method(scene_tree, "update_tree");
2326 undo_redo->add_do_reference(child);
2327 undo_redo->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
2328 }
2329
2330 undo_redo->commit_action();
2331 _push_item(c);
2332 editor_selection->clear();
2333 editor_selection->add_node(child);
2334 if (Object::cast_to<Control>(c)) {
2335 //make editor more comfortable, so some controls don't appear super shrunk
2336 Control *ct = Object::cast_to<Control>(c);
2337
2338 Size2 ms = ct->get_minimum_size();
2339 if (ms.width < 4) {
2340 ms.width = 40;
2341 }
2342 if (ms.height < 4) {
2343 ms.height = 40;
2344 }
2345 if (ct->is_layout_rtl()) {
2346 ct->set_position(ct->get_position() - Vector2(ms.x, 0));
2347 }
2348 ct->set_size(ms);
2349 }
2350
2351 emit_signal(SNAME("node_created"), c);
2352}
2353
2354void SceneTreeDock::_create() {
2355 if (current_option == TOOL_NEW) {
2356 Node *parent = nullptr;
2357
2358 if (edited_scene) {
2359 // If root exists in edited scene
2360 parent = scene_tree->get_selected();
2361 if (!parent) {
2362 parent = edited_scene;
2363 }
2364
2365 } else {
2366 // If no root exist in edited scene
2367 parent = scene_root;
2368 ERR_FAIL_NULL(parent);
2369 }
2370
2371 _do_create(parent);
2372
2373 } else if (current_option == TOOL_REPLACE) {
2374 List<Node *> selection = editor_selection->get_selected_node_list();
2375 ERR_FAIL_COND(selection.size() <= 0);
2376
2377 EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
2378 ur->create_action(TTR("Change type of node(s)"), UndoRedo::MERGE_DISABLE, selection.front()->get());
2379
2380 for (Node *n : selection) {
2381 ERR_FAIL_NULL(n);
2382
2383 Variant c = create_dialog->instantiate_selected();
2384
2385 ERR_FAIL_COND(!c);
2386 Node *new_node = Object::cast_to<Node>(c);
2387 ERR_FAIL_NULL(new_node);
2388 replace_node(n, new_node);
2389 }
2390
2391 ur->commit_action(false);
2392 } else if (current_option == TOOL_REPARENT_TO_NEW_NODE) {
2393 List<Node *> selection = editor_selection->get_selected_node_list();
2394 ERR_FAIL_COND(selection.size() <= 0);
2395
2396 // Find top level node in selection
2397 bool only_one_top_node = true;
2398
2399 Node *first = selection.front()->get();
2400 ERR_FAIL_NULL(first);
2401 int smaller_path_to_top = first->get_path_to(scene_root).get_name_count();
2402 Node *top_node = first;
2403
2404 for (List<Node *>::Element *E = selection.front()->next(); E; E = E->next()) {
2405 Node *n = E->get();
2406 ERR_FAIL_NULL(n);
2407
2408 int path_length = n->get_path_to(scene_root).get_name_count();
2409
2410 if (top_node != n) {
2411 if (smaller_path_to_top > path_length) {
2412 top_node = n;
2413 smaller_path_to_top = path_length;
2414 only_one_top_node = true;
2415 } else if (smaller_path_to_top == path_length) {
2416 if (only_one_top_node && top_node->get_parent() != n->get_parent()) {
2417 only_one_top_node = false;
2418 }
2419 }
2420 }
2421 }
2422
2423 Node *parent = nullptr;
2424 if (only_one_top_node) {
2425 parent = top_node->get_parent();
2426 } else {
2427 parent = top_node->get_parent()->get_parent();
2428 }
2429
2430 _do_create(parent);
2431
2432 Vector<Node *> nodes;
2433 for (Node *E : selection) {
2434 nodes.push_back(E);
2435 }
2436
2437 // This works because editor_selection was cleared and populated with last created node in _do_create()
2438 Node *last_created = editor_selection->get_selected_node_list().front()->get();
2439 _do_reparent(last_created, -1, nodes, true);
2440 }
2441
2442 scene_tree->get_scene_tree()->grab_focus();
2443}
2444
2445void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node) {
2446 EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
2447 ur->create_action(TTR("Change type of node(s)"), UndoRedo::MERGE_DISABLE, p_node);
2448
2449 ur->add_do_method(this, "replace_node", p_node, p_by_node, true, false);
2450 ur->add_do_reference(p_by_node);
2451
2452 _replace_node(p_node, p_by_node, true, false);
2453
2454 ur->add_undo_method(this, "replace_node", p_by_node, p_node, false, false);
2455 ur->add_undo_reference(p_node);
2456
2457 perform_node_replace(nullptr, p_node, p_by_node);
2458
2459 ur->commit_action(false);
2460}
2461
2462void SceneTreeDock::_replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties, bool p_remove_old) {
2463 ERR_FAIL_COND_MSG(!p_node->is_inside_tree(), "_replace_node() can't be called on a node outside of tree. You might have called it twice.");
2464 Node *n = p_node;
2465 Node *newnode = p_by_node;
2466
2467 if (p_keep_properties) {
2468 Node *default_oldnode = Object::cast_to<Node>(ClassDB::instantiate(n->get_class()));
2469 List<PropertyInfo> pinfo;
2470 n->get_property_list(&pinfo);
2471
2472 for (const PropertyInfo &E : pinfo) {
2473 if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
2474 continue;
2475 }
2476
2477 if (default_oldnode->get(E.name) != n->get(E.name)) {
2478 newnode->set(E.name, n->get(E.name));
2479 }
2480 }
2481
2482 memdelete(default_oldnode);
2483 }
2484
2485 _push_item(nullptr);
2486
2487 //reconnect signals
2488 List<MethodInfo> sl;
2489
2490 n->get_signal_list(&sl);
2491 for (const MethodInfo &E : sl) {
2492 List<Object::Connection> cl;
2493 n->get_signal_connection_list(E.name, &cl);
2494
2495 for (const Object::Connection &c : cl) {
2496 if (!(c.flags & Object::CONNECT_PERSIST)) {
2497 continue;
2498 }
2499 newnode->connect(c.signal.get_name(), c.callable, Object::CONNECT_PERSIST);
2500 }
2501 }
2502
2503 String newname = n->get_name();
2504
2505 List<Node *> to_erase;
2506 for (int i = 0; i < n->get_child_count(); i++) {
2507 if (n->get_child(i)->get_owner() == nullptr && n->is_owned_by_parent()) {
2508 to_erase.push_back(n->get_child(i));
2509 }
2510 }
2511 n->replace_by(newnode, true);
2512
2513 //small hack to make collisionshapes and other kind of nodes to work
2514 for (int i = 0; i < newnode->get_child_count(); i++) {
2515 Node *c = newnode->get_child(i);
2516 c->call("set_transform", c->call("get_transform"));
2517 }
2518 //p_remove_old was added to support undo
2519 if (p_remove_old) {
2520 EditorUndoRedoManager::get_singleton()->clear_history();
2521 }
2522 newnode->set_name(newname);
2523
2524 _push_item(newnode);
2525
2526 if (p_remove_old) {
2527 memdelete(n);
2528
2529 while (to_erase.front()) {
2530 memdelete(to_erase.front()->get());
2531 to_erase.pop_front();
2532 }
2533 }
2534}
2535
2536void SceneTreeDock::perform_node_replace(Node *p_base, Node *p_node, Node *p_by_node) {
2537 if (!p_base) {
2538 p_base = edited_scene;
2539 }
2540
2541 if (!p_base) {
2542 return;
2543 }
2544
2545 // Renaming node used in node properties.
2546 List<PropertyInfo> properties;
2547 p_base->get_property_list(&properties);
2548
2549 for (const PropertyInfo &E : properties) {
2550 if (!(E.usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR))) {
2551 continue;
2552 }
2553 String propertyname = E.name;
2554 Variant old_variant = p_base->get(propertyname);
2555 Variant updated_variant = old_variant;
2556 String warn_message;
2557
2558 if (_check_node_recursive(updated_variant, p_node, p_by_node, E.hint_string, warn_message)) {
2559 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2560 undo_redo->add_do_property(p_base, propertyname, updated_variant);
2561 undo_redo->add_undo_property(p_base, propertyname, old_variant);
2562 p_base->set(propertyname, updated_variant);
2563 if (!warn_message.is_empty()) {
2564 String node_path = (String(edited_scene->get_name()) + "/" + String(edited_scene->get_path_to(p_base))).trim_suffix("/.");
2565 WARN_PRINT(warn_message + vformat(TTR("Removing the node from variable \"%s\" on node \"%s\"."), propertyname, node_path));
2566 }
2567 }
2568 }
2569
2570 for (int i = 0; i < p_base->get_child_count(); i++) {
2571 perform_node_replace(p_base->get_child(i), p_node, p_by_node);
2572 }
2573}
2574
2575bool SceneTreeDock::_check_node_recursive(Variant &r_variant, Node *p_node, Node *p_by_node, const String type_hint, String &r_warn_message) {
2576 switch (r_variant.get_type()) {
2577 case Variant::OBJECT: {
2578 if (p_node == r_variant) {
2579 if (p_by_node->is_class(type_hint) || EditorNode::get_singleton()->is_object_of_custom_type(p_by_node, type_hint)) {
2580 r_variant = p_by_node;
2581 } else {
2582 r_variant = memnew(Object);
2583 r_warn_message = vformat(TTR("The node's new type is incompatible with an exported variable (expected %s, but type is %s)."), type_hint, p_by_node->get_class());
2584 }
2585 return true;
2586 }
2587 } break;
2588
2589 case Variant::ARRAY: {
2590 Array a = r_variant;
2591 bool updated = false;
2592 for (int i = 0; i < a.size(); i++) {
2593 Variant value = a[i];
2594 if (_check_node_recursive(value, p_node, p_by_node, type_hint.get_slice(":", 1), r_warn_message)) {
2595 if (!updated) {
2596 a = a.duplicate(); // Need to duplicate for undo-redo to work.
2597 updated = true;
2598 }
2599 a[i] = value;
2600 }
2601 }
2602 if (updated) {
2603 r_variant = a;
2604 return true;
2605 }
2606 } break;
2607 default: {
2608 }
2609 }
2610
2611 return false;
2612}
2613
2614void SceneTreeDock::set_edited_scene(Node *p_scene) {
2615 edited_scene = p_scene;
2616}
2617
2618void SceneTreeDock::set_selected(Node *p_node, bool p_emit_selected) {
2619 scene_tree->set_selected(p_node, p_emit_selected);
2620}
2621
2622void SceneTreeDock::_new_scene_from(String p_file) {
2623 List<Node *> selection = editor_selection->get_selected_node_list();
2624
2625 if (selection.size() != 1) {
2626 accept->set_text(TTR("This operation requires a single selected node."));
2627 accept->popup_centered();
2628 return;
2629 }
2630
2631 if (EditorNode::get_singleton()->is_scene_open(p_file)) {
2632 accept->set_text(TTR("Can't overwrite scene that is still open!"));
2633 accept->popup_centered();
2634 return;
2635 }
2636
2637 Node *base = selection.front()->get();
2638
2639 HashMap<const Node *, Node *> duplimap;
2640 Node *copy = base->duplicate_from_editor(duplimap);
2641
2642 if (copy) {
2643 // Handle Unique Nodes.
2644 for (int i = 0; i < copy->get_child_count(false); i++) {
2645 _set_node_owner_recursive(copy->get_child(i, false), copy);
2646 }
2647 // Root node cannot ever be unique name in its own Scene!
2648 copy->set_unique_name_in_owner(false);
2649
2650 Ref<PackedScene> sdata = memnew(PackedScene);
2651 Error err = sdata->pack(copy);
2652 memdelete(copy);
2653
2654 if (err != OK) {
2655 accept->set_text(TTR("Couldn't save new scene. Likely dependencies (instances) couldn't be satisfied."));
2656 accept->popup_centered();
2657 return;
2658 }
2659
2660 int flg = 0;
2661 if (EDITOR_GET("filesystem/on_save/compress_binary_resources")) {
2662 flg |= ResourceSaver::FLAG_COMPRESS;
2663 }
2664
2665 err = ResourceSaver::save(sdata, p_file, flg);
2666 if (err != OK) {
2667 accept->set_text(TTR("Error saving scene."));
2668 accept->popup_centered();
2669 return;
2670 }
2671 _replace_with_branch_scene(p_file, base);
2672 } else {
2673 accept->set_text(TTR("Error duplicating scene to save it."));
2674 accept->popup_centered();
2675 return;
2676 }
2677}
2678
2679void SceneTreeDock::_set_node_owner_recursive(Node *p_node, Node *p_owner) {
2680 if (!p_node->get_owner()) {
2681 p_node->set_owner(p_owner);
2682 }
2683
2684 for (int i = 0; i < p_node->get_child_count(false); i++) {
2685 _set_node_owner_recursive(p_node->get_child(i, false), p_owner);
2686 }
2687}
2688
2689static bool _is_node_visible(Node *p_node) {
2690 if (!p_node->get_owner()) {
2691 return false;
2692 }
2693 if (p_node->get_owner() != EditorNode::get_singleton()->get_edited_scene() && !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node->get_owner())) {
2694 return false;
2695 }
2696
2697 return true;
2698}
2699
2700static bool _has_visible_children(Node *p_node) {
2701 bool collapsed = p_node->is_displayed_folded();
2702 if (collapsed) {
2703 return false;
2704 }
2705
2706 for (int i = 0; i < p_node->get_child_count(); i++) {
2707 Node *child = p_node->get_child(i);
2708 if (!_is_node_visible(child)) {
2709 continue;
2710 }
2711
2712 return true;
2713 }
2714
2715 return false;
2716}
2717
2718void SceneTreeDock::_normalize_drop(Node *&to_node, int &to_pos, int p_type) {
2719 to_pos = -1;
2720
2721 if (p_type == -1) {
2722 //drop at above selected node
2723 if (to_node == EditorNode::get_singleton()->get_edited_scene()) {
2724 to_node = nullptr;
2725 ERR_FAIL_MSG("Cannot perform drop above the root node!");
2726 }
2727
2728 to_pos = to_node->get_index(false);
2729 to_node = to_node->get_parent();
2730
2731 } else if (p_type == 1) {
2732 //drop at below selected node
2733 if (to_node == EditorNode::get_singleton()->get_edited_scene()) {
2734 //if at lower sibling of root node
2735 to_pos = 0; //just insert at beginning of root node
2736 return;
2737 }
2738
2739 Node *lower_sibling = nullptr;
2740
2741 if (_has_visible_children(to_node)) {
2742 to_pos = 0;
2743 } else {
2744 for (int i = to_node->get_index(false) + 1; i < to_node->get_parent()->get_child_count(false); i++) {
2745 Node *c = to_node->get_parent()->get_child(i, false);
2746 if (_is_node_visible(c)) {
2747 lower_sibling = c;
2748 break;
2749 }
2750 }
2751 if (lower_sibling) {
2752 to_pos = lower_sibling->get_index(false);
2753 }
2754
2755 to_node = to_node->get_parent();
2756 }
2757 }
2758}
2759
2760void SceneTreeDock::_files_dropped(Vector<String> p_files, NodePath p_to, int p_type) {
2761 Node *node = get_node(p_to);
2762 ERR_FAIL_NULL(node);
2763
2764 if (scene_tree->get_scene_tree()->get_drop_mode_flags() & Tree::DROP_MODE_INBETWEEN) {
2765 // Dropped PackedScene, instance it.
2766 int to_pos = -1;
2767 _normalize_drop(node, to_pos, p_type);
2768 _perform_instantiate_scenes(p_files, node, to_pos);
2769 } else {
2770 String res_path = p_files[0];
2771 StringName res_type = EditorFileSystem::get_singleton()->get_file_type(res_path);
2772 List<String> valid_properties;
2773
2774 List<PropertyInfo> pinfo;
2775 node->get_property_list(&pinfo);
2776
2777 for (const PropertyInfo &p : pinfo) {
2778 if (!(p.usage & PROPERTY_USAGE_EDITOR) || !(p.usage & PROPERTY_USAGE_STORAGE) || p.hint != PROPERTY_HINT_RESOURCE_TYPE) {
2779 continue;
2780 }
2781 Vector<String> valid_types = p.hint_string.split(",");
2782
2783 for (const String &prop_type : valid_types) {
2784 if (res_type == prop_type || ClassDB::is_parent_class(res_type, prop_type) || EditorNode::get_editor_data().script_class_is_parent(res_type, prop_type)) {
2785 valid_properties.push_back(p.name);
2786 break;
2787 }
2788 }
2789 }
2790
2791 if (valid_properties.size() > 1) {
2792 property_drop_node = node;
2793 resource_drop_path = res_path;
2794
2795 const EditorPropertyNameProcessor::Style style = InspectorDock::get_singleton()->get_property_name_style();
2796 menu_properties->clear();
2797 for (const String &p : valid_properties) {
2798 menu_properties->add_item(EditorPropertyNameProcessor::get_singleton()->process_name(p, style));
2799 menu_properties->set_item_metadata(-1, p);
2800 }
2801
2802 menu_properties->reset_size();
2803 menu_properties->set_position(get_screen_position() + get_local_mouse_position());
2804 menu_properties->popup();
2805 } else if (!valid_properties.is_empty()) {
2806 _perform_property_drop(node, valid_properties[0], ResourceLoader::load(res_path));
2807 }
2808 }
2809}
2810
2811void SceneTreeDock::_script_dropped(String p_file, NodePath p_to) {
2812 Ref<Script> scr = ResourceLoader::load(p_file);
2813 ERR_FAIL_COND(!scr.is_valid());
2814 Node *n = get_node(p_to);
2815
2816 if (!n) {
2817 return;
2818 }
2819
2820 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2821 if (Input::get_singleton()->is_key_pressed(Key::CTRL)) {
2822 Object *obj = ClassDB::instantiate(scr->get_instance_base_type());
2823 ERR_FAIL_NULL(obj);
2824
2825 Node *new_node = Object::cast_to<Node>(obj);
2826 if (!new_node) {
2827 if (!obj->is_ref_counted()) {
2828 memdelete(obj);
2829 }
2830 ERR_FAIL_MSG("Script does not extend Node-derived type.");
2831 }
2832 new_node->set_name(Node::adjust_name_casing(p_file.get_file().get_basename()));
2833 new_node->set_script(scr);
2834
2835 undo_redo->create_action(TTR("Instantiate Script"));
2836 undo_redo->add_do_method(n, "add_child", new_node, true);
2837 undo_redo->add_do_method(new_node, "set_owner", edited_scene);
2838 undo_redo->add_do_method(editor_selection, "clear");
2839 undo_redo->add_do_method(editor_selection, "add_node", new_node);
2840 undo_redo->add_do_reference(new_node);
2841 undo_redo->add_undo_method(n, "remove_child", new_node);
2842
2843 EditorDebuggerNode *ed = EditorDebuggerNode::get_singleton();
2844 undo_redo->add_do_method(ed, "live_debug_create_node", edited_scene->get_path_to(n), new_node->get_class(), new_node->get_name());
2845 undo_redo->add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(n)).path_join(new_node->get_name())));
2846 undo_redo->commit_action();
2847 } else {
2848 undo_redo->create_action(TTR("Attach Script"), UndoRedo::MERGE_DISABLE, n);
2849 undo_redo->add_do_method(InspectorDock::get_singleton(), "store_script_properties", n);
2850 undo_redo->add_undo_method(InspectorDock::get_singleton(), "store_script_properties", n);
2851 undo_redo->add_do_method(n, "set_script", scr);
2852 undo_redo->add_undo_method(n, "set_script", n->get_script());
2853 undo_redo->add_do_method(InspectorDock::get_singleton(), "apply_script_properties", n);
2854 undo_redo->add_undo_method(InspectorDock::get_singleton(), "apply_script_properties", n);
2855 undo_redo->add_do_method(this, "_update_script_button");
2856 undo_redo->add_undo_method(this, "_update_script_button");
2857 undo_redo->commit_action();
2858 }
2859}
2860
2861void SceneTreeDock::_nodes_dragged(Array p_nodes, NodePath p_to, int p_type) {
2862 if (!_validate_no_foreign()) {
2863 return;
2864 }
2865
2866 List<Node *> selection = editor_selection->get_selected_node_list();
2867
2868 if (selection.is_empty()) {
2869 return; //nothing to reparent
2870 }
2871
2872 Node *to_node = get_node(p_to);
2873 if (!to_node) {
2874 return;
2875 }
2876
2877 Vector<Node *> nodes;
2878 for (Node *E : selection) {
2879 nodes.push_back(E);
2880 }
2881
2882 int to_pos = -1;
2883
2884 _normalize_drop(to_node, to_pos, p_type);
2885 _do_reparent(to_node, to_pos, nodes, !Input::get_singleton()->is_key_pressed(Key::SHIFT));
2886}
2887
2888void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) {
2889 if (p_depth > 8) {
2890 return;
2891 }
2892
2893 List<PropertyInfo> pinfo;
2894 p_obj->get_property_list(&pinfo);
2895 for (const PropertyInfo &E : pinfo) {
2896 if (!(E.usage & PROPERTY_USAGE_EDITOR)) {
2897 continue;
2898 }
2899 if (E.hint != PROPERTY_HINT_RESOURCE_TYPE) {
2900 continue;
2901 }
2902
2903 Variant value = p_obj->get(E.name);
2904 if (value.get_type() != Variant::OBJECT) {
2905 continue;
2906 }
2907 Object *obj = value;
2908 if (!obj) {
2909 continue;
2910 }
2911
2912 Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(obj);
2913
2914 if (menu->get_item_count() == 0) {
2915 menu->add_submenu_item(TTR("Sub-Resources"), "Sub-Resources");
2916 }
2917 menu_subresources->add_icon_item(icon, E.name.capitalize(), EDIT_SUBRESOURCE_BASE + subresources.size());
2918 menu_subresources->set_item_indent(-1, p_depth);
2919 subresources.push_back(obj->get_instance_id());
2920
2921 _add_children_to_popup(obj, p_depth + 1);
2922 }
2923}
2924
2925void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
2926 if (!EditorNode::get_singleton()->get_edited_scene()) {
2927 menu->clear();
2928 if (profile_allow_editing) {
2929 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("Add")), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
2930 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("Instance")), ED_GET_SHORTCUT("scene_tree/instantiate_scene"), TOOL_INSTANTIATE);
2931 }
2932
2933 menu->reset_size();
2934 menu->set_position(get_screen_position() + p_menu_pos);
2935 menu->popup();
2936 return;
2937 }
2938
2939 List<Node *> selection = editor_selection->get_selected_node_list();
2940 List<Node *> full_selection = editor_selection->get_full_selected_node_list(); // Above method only returns nodes with common parent.
2941
2942 if (selection.size() == 0) {
2943 return;
2944 }
2945
2946 menu->clear();
2947
2948 Ref<Script> existing_script;
2949 bool existing_script_removable = true;
2950 if (selection.size() == 1) {
2951 Node *selected = selection[0];
2952
2953 if (profile_allow_editing) {
2954 subresources.clear();
2955 menu_subresources->clear();
2956 menu_subresources->reset_size();
2957 _add_children_to_popup(selection.front()->get(), 0);
2958 if (menu->get_item_count() > 0) {
2959 menu->add_separator();
2960 }
2961
2962 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("Add")), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
2963 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("Instance")), ED_GET_SHORTCUT("scene_tree/instantiate_scene"), TOOL_INSTANTIATE);
2964 }
2965 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("Collapse")), ED_GET_SHORTCUT("scene_tree/expand_collapse_all"), TOOL_EXPAND_COLLAPSE);
2966 menu->add_separator();
2967
2968 existing_script = selected->get_script();
2969
2970 if (EditorNode::get_singleton()->get_object_custom_type_base(selected) == existing_script) {
2971 existing_script_removable = false;
2972 }
2973 }
2974
2975 if (profile_allow_editing) {
2976 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ActionCut")), ED_GET_SHORTCUT("scene_tree/cut_node"), TOOL_CUT);
2977 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ActionCopy")), ED_GET_SHORTCUT("scene_tree/copy_node"), TOOL_COPY);
2978 if (selection.size() == 1 && !node_clipboard.is_empty()) {
2979 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ActionPaste")), ED_GET_SHORTCUT("scene_tree/paste_node"), TOOL_PASTE);
2980 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ActionPaste")), ED_GET_SHORTCUT("scene_tree/paste_node_as_sibling"), TOOL_PASTE_AS_SIBLING);
2981 if (selection.front()->get() == edited_scene) {
2982 menu->set_item_disabled(-1, true);
2983 }
2984 }
2985 menu->add_separator();
2986 }
2987
2988 if (profile_allow_script_editing) {
2989 bool add_separator = false;
2990
2991 if (full_selection.size() == 1) {
2992 add_separator = true;
2993 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ScriptCreate")), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT);
2994 if (existing_script.is_valid()) {
2995 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ScriptExtend")), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_EXTEND_SCRIPT);
2996 }
2997 }
2998 if (existing_script.is_valid() && existing_script_removable) {
2999 add_separator = true;
3000 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ScriptRemove")), ED_GET_SHORTCUT("scene_tree/detach_script"), TOOL_DETACH_SCRIPT);
3001 } else if (full_selection.size() > 1) {
3002 bool script_exists = false;
3003 for (Node *E : full_selection) {
3004 if (!E->get_script().is_null()) {
3005 script_exists = true;
3006 break;
3007 }
3008 }
3009
3010 if (script_exists) {
3011 add_separator = true;
3012 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ScriptRemove")), ED_GET_SHORTCUT("scene_tree/detach_script"), TOOL_DETACH_SCRIPT);
3013 }
3014 }
3015
3016 if (add_separator && profile_allow_editing) {
3017 menu->add_separator();
3018 }
3019 }
3020
3021 if (profile_allow_editing) {
3022 bool add_separator = false;
3023
3024 if (full_selection.size() == 1) {
3025 add_separator = true;
3026 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("Rename")), ED_GET_SHORTCUT("scene_tree/rename"), TOOL_RENAME);
3027 }
3028
3029 bool can_replace = true;
3030 for (Node *E : selection) {
3031 if (E != edited_scene && (E->get_owner() != edited_scene || !E->get_scene_file_path().is_empty())) {
3032 can_replace = false;
3033 break;
3034 }
3035 }
3036
3037 if (can_replace) {
3038 add_separator = true;
3039 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("Reload")), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE);
3040 }
3041
3042 if (scene_tree->get_selected() != edited_scene) {
3043 if (add_separator) {
3044 menu->add_separator();
3045 }
3046 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("MoveUp")), ED_GET_SHORTCUT("scene_tree/move_up"), TOOL_MOVE_UP);
3047 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("MoveDown")), ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN);
3048 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("Duplicate")), ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE);
3049 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("Reparent")), ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT);
3050 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ReparentToNewNode")), ED_GET_SHORTCUT("scene_tree/reparent_to_new_node"), TOOL_REPARENT_TO_NEW_NODE);
3051 if (selection.size() == 1) {
3052 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("NewRoot")), ED_GET_SHORTCUT("scene_tree/make_root"), TOOL_MAKE_ROOT);
3053 }
3054 }
3055 }
3056 if (selection.size() == 1) {
3057 if (profile_allow_editing) {
3058 menu->add_separator();
3059 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("CreateNewSceneFrom")), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);
3060 }
3061
3062 if (full_selection.size() == 1) {
3063 menu->add_separator();
3064 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("CopyNodePath")), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH);
3065 }
3066 }
3067
3068 if (profile_allow_editing) {
3069 // Allow multi-toggling scene unique names but only if all selected nodes are owned by the edited scene root.
3070 bool all_owned = true;
3071 for (Node *node : full_selection) {
3072 if (node->get_owner() != EditorNode::get_singleton()->get_edited_scene()) {
3073 all_owned = false;
3074 break;
3075 }
3076 }
3077 if (all_owned) {
3078 // Group "toggle_unique_name" with "copy_node_path", if it is available.
3079 if (menu->get_item_index(TOOL_COPY_NODE_PATH) == -1) {
3080 menu->add_separator();
3081 }
3082 Node *node = full_selection[0];
3083 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("SceneUniqueName")), ED_GET_SHORTCUT("scene_tree/toggle_unique_name"), TOOL_TOGGLE_SCENE_UNIQUE_NAME);
3084 menu->set_item_text(menu->get_item_index(TOOL_TOGGLE_SCENE_UNIQUE_NAME), node->is_unique_name_in_owner() ? TTR("Revoke Unique Name") : TTR("Access as Unique Name"));
3085 }
3086 }
3087
3088 if (selection.size() == 1) {
3089 bool is_external = (!selection[0]->get_scene_file_path().is_empty());
3090 if (is_external) {
3091 bool is_inherited = selection[0]->get_scene_inherited_state() != nullptr;
3092 bool is_top_level = selection[0]->get_owner() == nullptr;
3093 if (is_inherited && is_top_level) {
3094 menu->add_separator();
3095 if (profile_allow_editing) {
3096 menu->add_item(TTR("Clear Inheritance"), TOOL_SCENE_CLEAR_INHERITANCE);
3097 }
3098 menu->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTR("Open in Editor"), TOOL_SCENE_OPEN_INHERITED);
3099 } else if (!is_top_level) {
3100 menu->add_separator();
3101 bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(selection[0]);
3102 bool placeholder = selection[0]->get_scene_instance_load_placeholder();
3103 if (profile_allow_editing) {
3104 menu->add_check_item(TTR("Editable Children"), TOOL_SCENE_EDITABLE_CHILDREN);
3105 menu->add_check_item(TTR("Load As Placeholder"), TOOL_SCENE_USE_PLACEHOLDER);
3106 menu->add_item(TTR("Make Local"), TOOL_SCENE_MAKE_LOCAL);
3107 }
3108 menu->add_icon_item(get_editor_theme_icon(SNAME("Load")), TTR("Open in Editor"), TOOL_SCENE_OPEN);
3109 if (profile_allow_editing) {
3110 menu->set_item_checked(menu->get_item_idx_from_text(TTR("Editable Children")), editable);
3111 menu->set_item_checked(menu->get_item_idx_from_text(TTR("Load As Placeholder")), placeholder);
3112 }
3113 }
3114 }
3115 }
3116
3117#ifdef MODULE_REGEX_ENABLED
3118 if (profile_allow_editing && selection.size() > 1) {
3119 //this is not a commonly used action, it makes no sense for it to be where it was nor always present.
3120 menu->add_separator();
3121 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("Rename")), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME);
3122 }
3123#endif // MODULE_REGEX_ENABLED
3124 menu->add_separator();
3125 menu->add_icon_item(get_editor_theme_icon(SNAME("Help")), TTR("Open Documentation"), TOOL_OPEN_DOCUMENTATION);
3126
3127 if (profile_allow_editing) {
3128 menu->add_separator();
3129 menu->add_icon_shortcut(get_editor_theme_icon(SNAME("Remove")), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), Key::KEY_DELETE), TOOL_ERASE);
3130 }
3131 menu->reset_size();
3132 menu->set_position(p_menu_pos);
3133 menu->popup();
3134}
3135
3136void SceneTreeDock::_update_tree_menu() {
3137 PopupMenu *tree_menu = button_tree_menu->get_popup();
3138 tree_menu->clear();
3139
3140 _append_filter_options_to(tree_menu);
3141
3142 tree_menu->add_separator();
3143 tree_menu->add_check_item(TTR("Auto Expand to Selected"), TOOL_AUTO_EXPAND);
3144 tree_menu->set_item_checked(tree_menu->get_item_index(TOOL_AUTO_EXPAND), EDITOR_GET("docks/scene_tree/auto_expand_to_selected"));
3145
3146 PopupMenu *resource_list = memnew(PopupMenu);
3147 resource_list->set_name("AllResources");
3148 resource_list->connect("about_to_popup", callable_mp(this, &SceneTreeDock::_list_all_subresources).bind(resource_list));
3149 resource_list->connect("index_pressed", callable_mp(this, &SceneTreeDock::_edit_subresource).bind(resource_list));
3150 tree_menu->add_child(resource_list);
3151 tree_menu->add_submenu_item(TTR("All Scene Sub-Resources"), "AllResources");
3152}
3153
3154void SceneTreeDock::_filter_changed(const String &p_filter) {
3155 scene_tree->set_filter(p_filter);
3156
3157 String warning = scene_tree->get_filter_term_warning();
3158 if (!warning.is_empty()) {
3159 filter->add_theme_icon_override(SNAME("clear"), get_editor_theme_icon(SNAME("NodeWarning")));
3160 filter->set_tooltip_text(warning);
3161 } else {
3162 filter->remove_theme_icon_override(SNAME("clear"));
3163 filter->set_tooltip_text("");
3164 }
3165}
3166
3167void SceneTreeDock::_filter_gui_input(const Ref<InputEvent> &p_event) {
3168 Ref<InputEventMouseButton> mb = p_event;
3169 if (mb.is_null()) {
3170 return;
3171 }
3172
3173 if (mb->is_pressed() && mb->get_button_index() == MouseButton::MIDDLE) {
3174 filter_quick_menu->clear();
3175
3176 _append_filter_options_to(filter_quick_menu, false);
3177 filter_quick_menu->set_position(get_screen_position() + get_local_mouse_position());
3178 filter_quick_menu->reset_size();
3179 filter_quick_menu->popup();
3180 filter_quick_menu->grab_focus();
3181 accept_event();
3182 }
3183}
3184
3185void SceneTreeDock::_filter_option_selected(int p_option) {
3186 String filter_parameter;
3187 switch (p_option) {
3188 case FILTER_BY_TYPE: {
3189 filter_parameter = "type";
3190 } break;
3191 case FILTER_BY_GROUP: {
3192 filter_parameter = "group";
3193 } break;
3194 }
3195
3196 if (!filter_parameter.is_empty()) {
3197 set_filter((get_filter() + " " + filter_parameter + ":").strip_edges());
3198 filter->set_caret_column(filter->get_text().length());
3199 filter->grab_focus();
3200 }
3201}
3202
3203void SceneTreeDock::_append_filter_options_to(PopupMenu *p_menu, bool p_include_separator) {
3204 if (p_include_separator) {
3205 p_menu->add_separator();
3206
3207 p_menu->set_item_text(-1, TTR("Filters"));
3208 p_menu->set_item_indent(-1, -2);
3209 }
3210
3211 p_menu->add_item(TTR("Filter by Type"), FILTER_BY_TYPE);
3212 p_menu->add_item(TTR("Filter by Group"), FILTER_BY_GROUP);
3213 p_menu->set_item_tooltip(p_menu->get_item_index(FILTER_BY_TYPE), TTR("Selects all Nodes of the given type."));
3214 p_menu->set_item_tooltip(p_menu->get_item_index(FILTER_BY_GROUP), TTR("Selects all Nodes belonging to the given group.\nIf empty, selects any Node belonging to any group."));
3215}
3216
3217String SceneTreeDock::get_filter() {
3218 return filter->get_text();
3219}
3220
3221void SceneTreeDock::set_filter(const String &p_filter) {
3222 filter->set_text(p_filter);
3223 scene_tree->set_filter(p_filter);
3224}
3225
3226void SceneTreeDock::save_branch_to_file(String p_directory) {
3227 new_scene_from_dialog->set_current_dir(p_directory);
3228 _tool_selected(TOOL_NEW_SCENE_FROM);
3229}
3230
3231void SceneTreeDock::_focus_node() {
3232 Node *node = scene_tree->get_selected();
3233 ERR_FAIL_NULL(node);
3234
3235 if (node->is_class("CanvasItem")) {
3236 CanvasItemEditorPlugin *editor = Object::cast_to<CanvasItemEditorPlugin>(editor_data->get_editor_by_name("2D"));
3237 editor->get_canvas_item_editor()->focus_selection();
3238 } else {
3239 Node3DEditorPlugin *editor = Object::cast_to<Node3DEditorPlugin>(editor_data->get_editor_by_name("3D"));
3240 editor->get_spatial_editor()->get_editor_viewport(0)->focus_selection();
3241 }
3242}
3243
3244void SceneTreeDock::attach_script_to_selected(bool p_extend) {
3245 if (ScriptServer::get_language_count() == 0) {
3246 EditorNode::get_singleton()->show_warning(TTR("Cannot attach a script: there are no languages registered.\nThis is probably because this editor was built with all language modules disabled."));
3247 return;
3248 }
3249
3250 if (!profile_allow_script_editing) {
3251 return;
3252 }
3253
3254 List<Node *> selection = editor_selection->get_selected_node_list();
3255 if (selection.is_empty()) {
3256 return;
3257 }
3258
3259 Node *selected = scene_tree->get_selected();
3260 if (!selected) {
3261 selected = selection.front()->get();
3262 }
3263
3264 Ref<Script> existing = selected->get_script();
3265
3266 String path = selected->get_scene_file_path();
3267 if (path.is_empty()) {
3268 String root_path = editor_data->get_edited_scene_root()->get_scene_file_path();
3269 if (root_path.is_empty()) {
3270 path = String("res://").path_join(selected->get_name());
3271 } else {
3272 path = root_path.get_base_dir().path_join(selected->get_name());
3273 }
3274 }
3275
3276 String inherits = selected->get_class();
3277
3278 if (p_extend && existing.is_valid()) {
3279 for (int i = 0; i < ScriptServer::get_language_count(); i++) {
3280 ScriptLanguage *l = ScriptServer::get_language(i);
3281 if (l->get_type() == existing->get_class()) {
3282 String name = l->get_global_class_name(existing->get_path());
3283 if (ScriptServer::is_global_class(name) && EDITOR_GET("interface/editors/derive_script_globals_by_name").operator bool()) {
3284 inherits = name;
3285 } else if (l->can_inherit_from_file()) {
3286 inherits = "\"" + existing->get_path() + "\"";
3287 }
3288 break;
3289 }
3290 }
3291 }
3292
3293 script_create_dialog->connect("script_created", callable_mp(this, &SceneTreeDock::_script_created));
3294 script_create_dialog->connect("confirmed", callable_mp(this, &SceneTreeDock::_script_creation_closed));
3295 script_create_dialog->connect("canceled", callable_mp(this, &SceneTreeDock::_script_creation_closed));
3296 script_create_dialog->set_inheritance_base_type("Node");
3297 script_create_dialog->config(inherits, path);
3298 script_create_dialog->popup_centered();
3299}
3300
3301void SceneTreeDock::open_script_dialog(Node *p_for_node, bool p_extend) {
3302 scene_tree->set_selected(p_for_node, false);
3303
3304 if (p_extend) {
3305 _tool_selected(TOOL_EXTEND_SCRIPT);
3306 } else {
3307 _tool_selected(TOOL_ATTACH_SCRIPT);
3308 }
3309}
3310
3311void SceneTreeDock::attach_shader_to_selected(int p_preferred_mode) {
3312 if (selected_shader_material.is_null()) {
3313 return;
3314 }
3315
3316 String path = selected_shader_material->get_path();
3317 if (path.is_empty()) {
3318 String root_path;
3319 if (editor_data->get_edited_scene_root()) {
3320 root_path = editor_data->get_edited_scene_root()->get_scene_file_path();
3321 }
3322 String shader_name;
3323 if (selected_shader_material->get_name().is_empty()) {
3324 shader_name = root_path.get_file();
3325 } else {
3326 shader_name = selected_shader_material->get_name();
3327 }
3328 if (root_path.is_empty()) {
3329 path = String("res://").path_join(shader_name);
3330 } else {
3331 path = root_path.get_base_dir().path_join(shader_name);
3332 }
3333 }
3334
3335 shader_create_dialog->connect("shader_created", callable_mp(this, &SceneTreeDock::_shader_created));
3336 shader_create_dialog->connect("confirmed", callable_mp(this, &SceneTreeDock::_shader_creation_closed));
3337 shader_create_dialog->connect("canceled", callable_mp(this, &SceneTreeDock::_shader_creation_closed));
3338 shader_create_dialog->config(path, true, true, -1, p_preferred_mode);
3339 shader_create_dialog->popup_centered();
3340}
3341
3342void SceneTreeDock::open_shader_dialog(const Ref<ShaderMaterial> &p_for_material, int p_preferred_mode) {
3343 selected_shader_material = p_for_material;
3344 attach_shader_to_selected(p_preferred_mode);
3345}
3346
3347void SceneTreeDock::open_add_child_dialog() {
3348 create_dialog->set_base_type("CanvasItem");
3349 _tool_selected(TOOL_NEW, true);
3350 reset_create_dialog = true;
3351}
3352
3353void SceneTreeDock::open_instance_child_dialog() {
3354 _tool_selected(TOOL_INSTANTIATE, true);
3355}
3356
3357List<Node *> SceneTreeDock::paste_nodes(bool p_paste_as_sibling) {
3358 List<Node *> pasted_nodes;
3359
3360 if (node_clipboard.is_empty()) {
3361 return pasted_nodes;
3362 }
3363
3364 bool has_cycle = false;
3365 if (edited_scene && !edited_scene->get_scene_file_path().is_empty()) {
3366 for (Node *E : node_clipboard) {
3367 if (edited_scene->get_scene_file_path() == E->get_scene_file_path()) {
3368 has_cycle = true;
3369 break;
3370 }
3371 }
3372 }
3373
3374 if (has_cycle) {
3375 current_option = -1;
3376 accept->set_text(TTR("Can't paste root node into the same scene."));
3377 accept->popup_centered();
3378 return pasted_nodes;
3379 }
3380
3381 Node *paste_parent = edited_scene;
3382 Node *paste_sibling = nullptr;
3383
3384 List<Node *> selection = editor_selection->get_selected_node_list();
3385 if (selection.size() > 0) {
3386 paste_parent = selection.back()->get();
3387 }
3388
3389 if (p_paste_as_sibling) {
3390 if (paste_parent == edited_scene) {
3391 return pasted_nodes; // Don't paste as sibling of scene root.
3392 }
3393
3394 paste_sibling = paste_parent;
3395 paste_parent = paste_parent->get_parent();
3396 }
3397
3398 Node *owner = nullptr;
3399 if (paste_parent) {
3400 owner = paste_parent->get_owner();
3401 }
3402 if (!owner) {
3403 owner = paste_parent;
3404 }
3405
3406 EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
3407 if (paste_parent) {
3408 ur->create_action(vformat(p_paste_as_sibling ? TTR("Paste Node(s) as Sibling of %s") : TTR("Paste Node(s) as Child of %s"), paste_sibling ? paste_sibling->get_name() : paste_parent->get_name()), UndoRedo::MERGE_DISABLE, edited_scene);
3409 } else {
3410 ur->create_action(TTR("Paste Node(s) as Root"), UndoRedo::MERGE_DISABLE, edited_scene);
3411 }
3412 ur->add_do_method(editor_selection, "clear");
3413
3414 HashMap<Ref<Resource>, Ref<Resource>> resource_remap;
3415 String target_scene;
3416 if (edited_scene) {
3417 target_scene = edited_scene->get_scene_file_path();
3418 }
3419 if (target_scene != clipboard_source_scene) {
3420 if (!clipboard_resource_remap.has(target_scene)) {
3421 HashMap<Ref<Resource>, Ref<Resource>> remap;
3422 for (Node *E : node_clipboard) {
3423 _create_remap_for_node(E, remap);
3424 }
3425 clipboard_resource_remap[target_scene] = remap;
3426 }
3427 resource_remap = clipboard_resource_remap[target_scene];
3428 }
3429
3430 for (Node *node : node_clipboard) {
3431 HashMap<const Node *, Node *> duplimap;
3432
3433 Node *dup = node->duplicate_from_editor(duplimap, resource_remap);
3434 ERR_CONTINUE(!dup);
3435
3436 pasted_nodes.push_back(dup);
3437
3438 if (!paste_parent) {
3439 paste_parent = dup;
3440 owner = dup;
3441 dup->set_scene_file_path(String()); // Make sure the scene path is empty, to avoid accidental references.
3442 ur->add_do_method(EditorNode::get_singleton(), "set_edited_scene", dup);
3443 } else {
3444 ur->add_do_method(paste_parent, "add_child", dup, true);
3445 }
3446
3447 for (KeyValue<const Node *, Node *> &E2 : duplimap) {
3448 Node *d = E2.value;
3449 // When copying, all nodes that should have an owner assigned here were given node as an owner.
3450 if (d != dup && E2.key->get_owner() == node) {
3451 ur->add_do_method(d, "set_owner", owner);
3452 }
3453 }
3454
3455 if (dup != owner) {
3456 ur->add_do_method(dup, "set_owner", owner);
3457 }
3458 ur->add_do_method(editor_selection, "add_node", dup);
3459
3460 if (dup == paste_parent) {
3461 ur->add_undo_method(EditorNode::get_singleton(), "set_edited_scene", (Object *)nullptr);
3462 } else {
3463 ur->add_undo_method(paste_parent, "remove_child", dup);
3464 }
3465 ur->add_do_reference(dup);
3466
3467 if (node_clipboard.size() == 1) {
3468 ur->add_do_method(EditorNode::get_singleton(), "push_item", dup);
3469 }
3470 }
3471
3472 ur->commit_action();
3473 return pasted_nodes;
3474}
3475
3476List<Node *> SceneTreeDock::get_node_clipboard() const {
3477 return node_clipboard;
3478}
3479
3480void SceneTreeDock::add_remote_tree_editor(Control *p_remote) {
3481 ERR_FAIL_COND(remote_tree != nullptr);
3482 add_child(p_remote);
3483 remote_tree = p_remote;
3484 remote_tree->hide();
3485 remote_tree->connect("open", callable_mp(this, &SceneTreeDock::_load_request));
3486}
3487
3488void SceneTreeDock::show_remote_tree() {
3489 _remote_tree_selected();
3490}
3491
3492void SceneTreeDock::hide_remote_tree() {
3493 _local_tree_selected();
3494}
3495
3496void SceneTreeDock::show_tab_buttons() {
3497 button_hb->show();
3498}
3499
3500void SceneTreeDock::hide_tab_buttons() {
3501 button_hb->hide();
3502}
3503
3504void SceneTreeDock::_remote_tree_selected() {
3505 scene_tree->hide();
3506 create_root_dialog->hide();
3507 if (remote_tree) {
3508 remote_tree->show();
3509 }
3510 edit_remote->set_pressed(true);
3511 edit_local->set_pressed(false);
3512
3513 emit_signal(SNAME("remote_tree_selected"));
3514}
3515
3516void SceneTreeDock::_local_tree_selected() {
3517 if (!bool(EDITOR_GET("interface/editors/show_scene_tree_root_selection")) || get_tree()->get_edited_scene_root() != nullptr) {
3518 scene_tree->show();
3519 }
3520 if (remote_tree) {
3521 remote_tree->hide();
3522 }
3523 edit_remote->set_pressed(false);
3524 edit_local->set_pressed(true);
3525}
3526
3527void SceneTreeDock::_update_create_root_dialog() {
3528 EditorSettings::get_singleton()->set_setting("_use_favorites_root_selection", node_shortcuts_toggle->is_pressed());
3529 EditorSettings::get_singleton()->save();
3530 if (node_shortcuts_toggle->is_pressed()) {
3531 for (int i = 0; i < favorite_node_shortcuts->get_child_count(); i++) {
3532 favorite_node_shortcuts->get_child(i)->queue_free();
3533 }
3534
3535 Ref<FileAccess> f = FileAccess::open(EditorPaths::get_singleton()->get_project_settings_dir().path_join("favorites.Node"), FileAccess::READ);
3536 if (f.is_valid()) {
3537 while (!f->eof_reached()) {
3538 String l = f->get_line().strip_edges();
3539
3540 if (!l.is_empty()) {
3541 Button *button = memnew(Button);
3542 favorite_node_shortcuts->add_child(button);
3543 button->set_text(l);
3544 button->set_clip_text(true);
3545 String name = l.get_slicec(' ', 0);
3546 if (ScriptServer::is_global_class(name)) {
3547 name = ScriptServer::get_global_class_native_base(name);
3548 }
3549 button->set_icon(EditorNode::get_singleton()->get_class_icon(name));
3550 button->connect("pressed", callable_mp(this, &SceneTreeDock::_favorite_root_selected).bind(l));
3551 }
3552 }
3553 }
3554
3555 if (!favorite_node_shortcuts->is_visible_in_tree()) {
3556 favorite_node_shortcuts->show();
3557 beginner_node_shortcuts->hide();
3558 }
3559 } else {
3560 if (!beginner_node_shortcuts->is_visible_in_tree()) {
3561 beginner_node_shortcuts->show();
3562 favorite_node_shortcuts->hide();
3563 }
3564 button_clipboard->set_visible(!node_clipboard.is_empty());
3565 }
3566}
3567
3568void SceneTreeDock::_favorite_root_selected(const String &p_class) {
3569 selected_favorite_root = p_class;
3570 _tool_selected(TOOL_CREATE_FAVORITE);
3571}
3572
3573void SceneTreeDock::_feature_profile_changed() {
3574 Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();
3575
3576 if (profile.is_valid()) {
3577 profile_allow_editing = !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCENE_TREE);
3578 profile_allow_script_editing = !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT);
3579 bool profile_allow_3d = !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D);
3580
3581 button_3d->set_visible(profile_allow_3d);
3582 button_add->set_visible(profile_allow_editing);
3583 button_instance->set_visible(profile_allow_editing);
3584 scene_tree->set_can_rename(profile_allow_editing);
3585
3586 } else {
3587 button_3d->set_visible(true);
3588 button_add->set_visible(true);
3589 button_instance->set_visible(true);
3590 scene_tree->set_can_rename(true);
3591 profile_allow_editing = true;
3592 profile_allow_script_editing = true;
3593 }
3594
3595 _update_script_button();
3596}
3597
3598void SceneTreeDock::_clear_clipboard() {
3599 for (Node *E : node_clipboard) {
3600 memdelete(E);
3601 }
3602 node_clipboard.clear();
3603 clipboard_resource_remap.clear();
3604}
3605
3606void SceneTreeDock::_create_remap_for_node(Node *p_node, HashMap<Ref<Resource>, Ref<Resource>> &r_remap) {
3607 List<PropertyInfo> props;
3608 p_node->get_property_list(&props);
3609
3610 Vector<SceneState::PackState> states_stack;
3611 bool states_stack_ready = false;
3612
3613 for (const PropertyInfo &E : props) {
3614 if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
3615 continue;
3616 }
3617
3618 Variant v = p_node->get(E.name);
3619 if (v.is_ref_counted()) {
3620 Ref<Resource> res = v;
3621 if (res.is_valid()) {
3622 if (!states_stack_ready) {
3623 states_stack = PropertyUtils::get_node_states_stack(p_node);
3624 states_stack_ready = true;
3625 }
3626
3627 bool is_valid_default = false;
3628 Variant orig = PropertyUtils::get_property_default_value(p_node, E.name, &is_valid_default, &states_stack);
3629 if (is_valid_default && !PropertyUtils::is_property_value_different(v, orig)) {
3630 continue;
3631 }
3632
3633 if (res->is_built_in() && !r_remap.has(res)) {
3634 _create_remap_for_resource(res, r_remap);
3635 }
3636 }
3637 }
3638 }
3639
3640 for (int i = 0; i < p_node->get_child_count(); i++) {
3641 _create_remap_for_node(p_node->get_child(i), r_remap);
3642 }
3643}
3644
3645void SceneTreeDock::_create_remap_for_resource(Ref<Resource> p_resource, HashMap<Ref<Resource>, Ref<Resource>> &r_remap) {
3646 r_remap[p_resource] = p_resource->duplicate();
3647
3648 List<PropertyInfo> props;
3649 p_resource->get_property_list(&props);
3650
3651 for (const PropertyInfo &E : props) {
3652 if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
3653 continue;
3654 }
3655
3656 Variant v = p_resource->get(E.name);
3657 if (v.is_ref_counted()) {
3658 Ref<Resource> res = v;
3659 if (res.is_valid()) {
3660 if (res->is_built_in() && !r_remap.has(res)) {
3661 _create_remap_for_resource(res, r_remap);
3662 }
3663 }
3664 }
3665 }
3666}
3667
3668void SceneTreeDock::_list_all_subresources(PopupMenu *p_menu) {
3669 p_menu->clear();
3670
3671 List<Pair<Ref<Resource>, Node *>> all_resources;
3672 if (edited_scene) {
3673 _gather_resources(edited_scene, all_resources);
3674 }
3675
3676 HashMap<String, List<Pair<Ref<Resource>, Node *>>> resources_by_type;
3677 HashMap<Ref<Resource>, int> unique_resources;
3678
3679 for (const Pair<Ref<Resource>, Node *> &pair : all_resources) {
3680 if (!unique_resources.has(pair.first)) {
3681 resources_by_type[pair.first->get_class()].push_back(pair);
3682 }
3683 unique_resources[pair.first]++;
3684 }
3685
3686 for (KeyValue<String, List<Pair<Ref<Resource>, Node *>>> kv : resources_by_type) {
3687 p_menu->add_icon_item(EditorNode::get_singleton()->get_class_icon(kv.key), kv.key);
3688 p_menu->set_item_as_separator(-1, true);
3689
3690 for (const Pair<Ref<Resource>, Node *> &pair : kv.value) {
3691 String display_text;
3692 if (pair.first->get_name().is_empty()) {
3693 display_text = vformat(TTR("<Unnamed> at %s"), pair.second->get_name());
3694 } else {
3695 display_text = pair.first->get_name();
3696 }
3697
3698 if (unique_resources[pair.first] > 1) {
3699 display_text += " " + vformat(TTR("(used %d times)"), unique_resources[pair.first]);
3700 }
3701
3702 p_menu->add_item(display_text);
3703 p_menu->set_item_metadata(-1, pair.first->get_instance_id());
3704 }
3705 }
3706
3707 if (resources_by_type.is_empty()) {
3708 p_menu->add_item(TTR("None"));
3709 p_menu->set_item_disabled(-1, true);
3710 }
3711
3712 p_menu->reset_size();
3713}
3714
3715void SceneTreeDock::_gather_resources(Node *p_node, List<Pair<Ref<Resource>, Node *>> &r_resources) {
3716 if (p_node != edited_scene && p_node->get_owner() != edited_scene) {
3717 return;
3718 }
3719
3720 List<PropertyInfo> pinfo;
3721 p_node->get_property_list(&pinfo);
3722 for (const PropertyInfo &E : pinfo) {
3723 if (!(E.usage & PROPERTY_USAGE_EDITOR)) {
3724 continue;
3725 }
3726 if (E.hint != PROPERTY_HINT_RESOURCE_TYPE) {
3727 continue;
3728 }
3729
3730 Variant value = p_node->get(E.name);
3731 if (value.get_type() != Variant::OBJECT) {
3732 continue;
3733 }
3734 Ref<Resource> res = value;
3735 if (res.is_null()) {
3736 continue;
3737 }
3738
3739 if (!res->is_built_in() || res->get_path().get_slice("::", 0) != edited_scene->get_scene_file_path()) {
3740 // Ignore external and foreign resources.
3741 continue;
3742 }
3743
3744 const Pair<Ref<Resource>, Node *> pair(res, p_node);
3745 r_resources.push_back(pair);
3746 }
3747
3748 for (int i = 0; i < p_node->get_child_count(); i++) {
3749 _gather_resources(p_node->get_child(i), r_resources);
3750 }
3751}
3752
3753void SceneTreeDock::_edit_subresource(int p_idx, const PopupMenu *p_from_menu) {
3754 const ObjectID &id = p_from_menu->get_item_metadata(p_idx);
3755
3756 Object *obj = ObjectDB::get_instance(id);
3757 ERR_FAIL_NULL(obj);
3758
3759 _push_item(obj);
3760}
3761
3762void SceneTreeDock::_bind_methods() {
3763 ClassDB::bind_method(D_METHOD("_set_owners"), &SceneTreeDock::_set_owners);
3764
3765 ClassDB::bind_method(D_METHOD("_update_script_button"), &SceneTreeDock::_update_script_button);
3766
3767 ClassDB::bind_method(D_METHOD("instantiate"), &SceneTreeDock::instantiate);
3768 ClassDB::bind_method(D_METHOD("get_tree_editor"), &SceneTreeDock::get_tree_editor);
3769 ClassDB::bind_method(D_METHOD("replace_node"), &SceneTreeDock::_replace_node);
3770
3771 ADD_SIGNAL(MethodInfo("remote_tree_selected"));
3772 ADD_SIGNAL(MethodInfo("add_node_used"));
3773 ADD_SIGNAL(MethodInfo("node_created", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
3774}
3775
3776SceneTreeDock *SceneTreeDock::singleton = nullptr;
3777
3778void SceneTreeDock::_update_configuration_warning() {
3779 if (singleton) {
3780 MessageQueue::get_singleton()->push_callable(callable_mp(singleton->scene_tree, &SceneTreeEditor::update_warning));
3781 }
3782}
3783
3784SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data) {
3785 singleton = this;
3786 set_name("Scene");
3787 edited_scene = nullptr;
3788 editor_data = &p_editor_data;
3789 editor_selection = p_editor_selection;
3790 scene_root = p_scene_root;
3791
3792 VBoxContainer *vbc = this;
3793
3794 HBoxContainer *filter_hbc = memnew(HBoxContainer);
3795 filter_hbc->add_theme_constant_override("separate", 0);
3796
3797 ED_SHORTCUT("scene_tree/rename", TTR("Rename"), Key::F2);
3798 ED_SHORTCUT_OVERRIDE("scene_tree/rename", "macos", Key::ENTER);
3799
3800 ED_SHORTCUT("scene_tree/batch_rename", TTR("Batch Rename"), KeyModifierMask::SHIFT | Key::F2);
3801 ED_SHORTCUT_OVERRIDE("scene_tree/batch_rename", "macos", KeyModifierMask::SHIFT | Key::ENTER);
3802
3803 ED_SHORTCUT("scene_tree/add_child_node", TTR("Add Child Node..."), KeyModifierMask::CMD_OR_CTRL | Key::A);
3804 ED_SHORTCUT("scene_tree/instantiate_scene", TTR("Instantiate Child Scene..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::A);
3805 ED_SHORTCUT("scene_tree/expand_collapse_all", TTR("Expand/Collapse Branch"));
3806 ED_SHORTCUT("scene_tree/cut_node", TTR("Cut"), KeyModifierMask::CMD_OR_CTRL | Key::X);
3807 ED_SHORTCUT("scene_tree/copy_node", TTR("Copy"), KeyModifierMask::CMD_OR_CTRL | Key::C);
3808 ED_SHORTCUT("scene_tree/paste_node", TTR("Paste"), KeyModifierMask::CMD_OR_CTRL | Key::V);
3809 ED_SHORTCUT("scene_tree/paste_node_as_sibling", TTR("Paste as Sibling"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::V);
3810 ED_SHORTCUT("scene_tree/change_node_type", TTR("Change Type..."));
3811 ED_SHORTCUT("scene_tree/attach_script", TTR("Attach Script..."));
3812 ED_SHORTCUT("scene_tree/extend_script", TTR("Extend Script..."));
3813 ED_SHORTCUT("scene_tree/detach_script", TTR("Detach Script"));
3814 ED_SHORTCUT("scene_tree/move_up", TTR("Move Up"), KeyModifierMask::CMD_OR_CTRL | Key::UP);
3815 ED_SHORTCUT("scene_tree/move_down", TTR("Move Down"), KeyModifierMask::CMD_OR_CTRL | Key::DOWN);
3816 ED_SHORTCUT("scene_tree/duplicate", TTR("Duplicate"), KeyModifierMask::CMD_OR_CTRL | Key::D);
3817 ED_SHORTCUT("scene_tree/reparent", TTR("Reparent"));
3818 ED_SHORTCUT("scene_tree/reparent_to_new_node", TTR("Reparent to New Node"));
3819 ED_SHORTCUT("scene_tree/make_root", TTR("Make Scene Root"));
3820 ED_SHORTCUT("scene_tree/save_branch_as_scene", TTR("Save Branch as Scene"));
3821 ED_SHORTCUT("scene_tree/copy_node_path", TTR("Copy Node Path"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::C);
3822 ED_SHORTCUT("scene_tree/toggle_unique_name", TTR("Toggle Access as Unique Name"));
3823 ED_SHORTCUT("scene_tree/delete_no_confirm", TTR("Delete (No Confirm)"), KeyModifierMask::SHIFT | Key::KEY_DELETE);
3824 ED_SHORTCUT("scene_tree/delete", TTR("Delete"), Key::KEY_DELETE);
3825
3826 button_add = memnew(Button);
3827 button_add->set_flat(true);
3828 button_add->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_NEW, false));
3829 button_add->set_tooltip_text(TTR("Add/Create a New Node."));
3830 button_add->set_shortcut(ED_GET_SHORTCUT("scene_tree/add_child_node"));
3831 filter_hbc->add_child(button_add);
3832
3833 button_instance = memnew(Button);
3834 button_instance->set_flat(true);
3835 button_instance->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_INSTANTIATE, false));
3836 button_instance->set_tooltip_text(TTR("Instantiate a scene file as a Node. Creates an inherited scene if no root node exists."));
3837 button_instance->set_shortcut(ED_GET_SHORTCUT("scene_tree/instantiate_scene"));
3838 filter_hbc->add_child(button_instance);
3839 vbc->add_child(filter_hbc);
3840
3841 // The "Filter Nodes" text input above the Scene Tree Editor.
3842 filter = memnew(LineEdit);
3843 filter->set_h_size_flags(SIZE_EXPAND_FILL);
3844 filter->set_placeholder(TTR("Filter Nodes"));
3845 filter_hbc->add_child(filter);
3846 filter->add_theme_constant_override("minimum_character_width", 0);
3847 filter->connect("text_changed", callable_mp(this, &SceneTreeDock::_filter_changed));
3848 filter->connect("gui_input", callable_mp(this, &SceneTreeDock::_filter_gui_input));
3849 filter->get_menu()->connect("id_pressed", callable_mp(this, &SceneTreeDock::_filter_option_selected));
3850 _append_filter_options_to(filter->get_menu());
3851
3852 filter_quick_menu = memnew(PopupMenu);
3853 filter_quick_menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_filter_option_selected));
3854 filter->add_child(filter_quick_menu);
3855
3856 button_create_script = memnew(Button);
3857 button_create_script->set_flat(true);
3858 button_create_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_ATTACH_SCRIPT, false));
3859 button_create_script->set_tooltip_text(TTR("Attach a new or existing script to the selected node."));
3860 button_create_script->set_shortcut(ED_GET_SHORTCUT("scene_tree/attach_script"));
3861 filter_hbc->add_child(button_create_script);
3862 button_create_script->hide();
3863
3864 button_detach_script = memnew(Button);
3865 button_detach_script->set_flat(true);
3866 button_detach_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_DETACH_SCRIPT, false));
3867 button_detach_script->set_tooltip_text(TTR("Detach the script from the selected node."));
3868 button_detach_script->set_shortcut(ED_GET_SHORTCUT("scene_tree/detach_script"));
3869 filter_hbc->add_child(button_detach_script);
3870 button_detach_script->hide();
3871
3872 button_tree_menu = memnew(MenuButton);
3873 button_tree_menu->set_flat(true);
3874 button_tree_menu->set_tooltip_text(TTR("Extra scene options."));
3875 button_tree_menu->connect("about_to_popup", callable_mp(this, &SceneTreeDock::_update_tree_menu));
3876 filter_hbc->add_child(button_tree_menu);
3877
3878 PopupMenu *tree_menu = button_tree_menu->get_popup();
3879 tree_menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(false));
3880
3881 button_hb = memnew(HBoxContainer);
3882 vbc->add_child(button_hb);
3883
3884 edit_remote = memnew(Button);
3885 edit_remote->set_flat(true);
3886 button_hb->add_child(edit_remote);
3887 edit_remote->set_h_size_flags(SIZE_EXPAND_FILL);
3888 edit_remote->set_text(TTR("Remote"));
3889 edit_remote->set_toggle_mode(true);
3890 edit_remote->set_tooltip_text(TTR("If selected, the Remote scene tree dock will cause the project to stutter every time it updates.\nSwitch back to the Local scene tree dock to improve performance."));
3891 edit_remote->connect("pressed", callable_mp(this, &SceneTreeDock::_remote_tree_selected));
3892
3893 edit_local = memnew(Button);
3894 edit_local->set_flat(true);
3895 button_hb->add_child(edit_local);
3896 edit_local->set_h_size_flags(SIZE_EXPAND_FILL);
3897 edit_local->set_text(TTR("Local"));
3898 edit_local->set_toggle_mode(true);
3899 edit_local->set_pressed(true);
3900 edit_local->connect("pressed", callable_mp(this, &SceneTreeDock::_local_tree_selected));
3901
3902 remote_tree = nullptr;
3903 button_hb->hide();
3904
3905 create_root_dialog = memnew(VBoxContainer);
3906 vbc->add_child(create_root_dialog);
3907 create_root_dialog->set_v_size_flags(SIZE_EXPAND_FILL);
3908 create_root_dialog->hide();
3909
3910 scene_tree = memnew(SceneTreeEditor(false, true, true));
3911
3912 vbc->add_child(scene_tree);
3913 scene_tree->set_v_size_flags(SIZE_EXPAND | SIZE_FILL);
3914 scene_tree->connect("rmb_pressed", callable_mp(this, &SceneTreeDock::_tree_rmb));
3915
3916 scene_tree->connect("node_selected", callable_mp(this, &SceneTreeDock::_node_selected), CONNECT_DEFERRED);
3917 scene_tree->connect("node_renamed", callable_mp(this, &SceneTreeDock::_node_renamed), CONNECT_DEFERRED);
3918 scene_tree->connect("node_prerename", callable_mp(this, &SceneTreeDock::_node_prerenamed));
3919 scene_tree->connect("open", callable_mp(this, &SceneTreeDock::_load_request));
3920 scene_tree->connect("open_script", callable_mp(this, &SceneTreeDock::_script_open_request));
3921 scene_tree->connect("nodes_rearranged", callable_mp(this, &SceneTreeDock::_nodes_dragged));
3922 scene_tree->connect("files_dropped", callable_mp(this, &SceneTreeDock::_files_dropped));
3923 scene_tree->connect("script_dropped", callable_mp(this, &SceneTreeDock::_script_dropped));
3924 scene_tree->connect("nodes_dragged", callable_mp(this, &SceneTreeDock::_nodes_drag_begin));
3925
3926 scene_tree->get_scene_tree()->connect("item_icon_double_clicked", callable_mp(this, &SceneTreeDock::_focus_node));
3927
3928 editor_selection->connect("selection_changed", callable_mp(this, &SceneTreeDock::_selection_changed));
3929
3930 scene_tree->set_as_scene_tree_dock();
3931 scene_tree->set_editor_selection(editor_selection);
3932
3933 create_dialog = memnew(CreateDialog);
3934 create_dialog->set_base_type("Node");
3935 add_child(create_dialog);
3936 create_dialog->connect("create", callable_mp(this, &SceneTreeDock::_create));
3937 create_dialog->connect("favorites_updated", callable_mp(this, &SceneTreeDock::_update_create_root_dialog));
3938
3939#ifdef MODULE_REGEX_ENABLED
3940 rename_dialog = memnew(RenameDialog(scene_tree));
3941 add_child(rename_dialog);
3942#endif // MODULE_REGEX_ENABLED
3943
3944 script_create_dialog = memnew(ScriptCreateDialog);
3945 script_create_dialog->set_inheritance_base_type("Node");
3946 add_child(script_create_dialog);
3947
3948 shader_create_dialog = memnew(ShaderCreateDialog);
3949 add_child(shader_create_dialog);
3950
3951 reparent_dialog = memnew(ReparentDialog);
3952 add_child(reparent_dialog);
3953 reparent_dialog->connect("reparent", callable_mp(this, &SceneTreeDock::_node_reparent));
3954
3955 accept = memnew(AcceptDialog);
3956 add_child(accept);
3957
3958 quick_open = memnew(EditorQuickOpen);
3959 add_child(quick_open);
3960 quick_open->connect("quick_open", callable_mp(this, &SceneTreeDock::_quick_open));
3961
3962 set_process_shortcut_input(true);
3963
3964 delete_dialog = memnew(ConfirmationDialog);
3965 add_child(delete_dialog);
3966 delete_dialog->connect("confirmed", callable_mp(this, &SceneTreeDock::_delete_confirm).bind(false));
3967
3968 VBoxContainer *vb = memnew(VBoxContainer);
3969 delete_dialog->add_child(vb);
3970
3971 delete_dialog_label = memnew(Label);
3972 vb->add_child(delete_dialog_label);
3973
3974 delete_tracks_checkbox = memnew(CheckBox(TTR("Delete Related Animation Tracks")));
3975 delete_tracks_checkbox->set_pressed(true);
3976 vb->add_child(delete_tracks_checkbox);
3977
3978 editable_instance_remove_dialog = memnew(ConfirmationDialog);
3979 add_child(editable_instance_remove_dialog);
3980 editable_instance_remove_dialog->connect("confirmed", callable_mp(this, &SceneTreeDock::_toggle_editable_children_from_selection));
3981
3982 placeholder_editable_instance_remove_dialog = memnew(ConfirmationDialog);
3983 add_child(placeholder_editable_instance_remove_dialog);
3984 placeholder_editable_instance_remove_dialog->connect("confirmed", callable_mp(this, &SceneTreeDock::_toggle_placeholder_from_selection));
3985
3986 new_scene_from_dialog = memnew(EditorFileDialog);
3987 new_scene_from_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
3988 add_child(new_scene_from_dialog);
3989 new_scene_from_dialog->connect("file_selected", callable_mp(this, &SceneTreeDock::_new_scene_from));
3990
3991 menu = memnew(PopupMenu);
3992 add_child(menu);
3993 menu->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(false));
3994
3995 menu_subresources = memnew(PopupMenu);
3996 menu_subresources->set_name("Sub-Resources");
3997 menu_subresources->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(false));
3998 menu->add_child(menu_subresources);
3999
4000 menu_properties = memnew(PopupMenu);
4001 add_child(menu_properties);
4002 menu_properties->connect("id_pressed", callable_mp(this, &SceneTreeDock::_property_selected));
4003
4004 clear_inherit_confirm = memnew(ConfirmationDialog);
4005 clear_inherit_confirm->set_text(TTR("Clear Inheritance? (No Undo!)"));
4006 clear_inherit_confirm->set_ok_button_text(TTR("Clear"));
4007 add_child(clear_inherit_confirm);
4008
4009 set_process_input(true);
4010 set_process(true);
4011
4012 EDITOR_DEF("interface/editors/show_scene_tree_root_selection", true);
4013 EDITOR_DEF("interface/editors/derive_script_globals_by_name", true);
4014 EDITOR_DEF("docks/scene_tree/ask_before_deleting_related_animation_tracks", true);
4015 EDITOR_DEF("_use_favorites_root_selection", false);
4016
4017 Resource::_update_configuration_warning = _update_configuration_warning;
4018}
4019
4020SceneTreeDock::~SceneTreeDock() {
4021 singleton = nullptr;
4022 if (!node_clipboard.is_empty()) {
4023 _clear_clipboard();
4024 }
4025}
4026