summaryrefslogtreecommitdiff
path: root/editor/editor_node.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/editor_node.cpp')
-rw-r--r--editor/editor_node.cpp204
1 files changed, 123 insertions, 81 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index b1b40eb52a..19d991b112 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -288,7 +288,7 @@ void EditorNode::_update_scene_tabs() {
icon = EditorNode::get_singleton()->get_object_icon(type_node, "Node");
}
- bool unsaved = get_undo_redo()->is_history_unsaved(editor_data.get_scene_history_id(i));
+ bool unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(editor_data.get_scene_history_id(i));
scene_tabs->add_tab(disambiguated_scene_names[i] + (unsaved ? "(*)" : ""), icon);
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) {
@@ -533,8 +533,8 @@ void EditorNode::_notification(int p_what) {
opening_prev = false;
}
- bool global_unsaved = get_undo_redo()->is_history_unsaved(EditorUndoRedoManager::GLOBAL_HISTORY);
- bool scene_or_global_unsaved = global_unsaved || get_undo_redo()->is_history_unsaved(editor_data.get_current_edited_scene_history_id());
+ bool global_unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(EditorUndoRedoManager::GLOBAL_HISTORY);
+ bool scene_or_global_unsaved = global_unsaved || EditorUndoRedoManager::get_singleton()->is_history_unsaved(editor_data.get_current_edited_scene_history_id());
if (unsaved_cache != scene_or_global_unsaved) {
unsaved_cache = scene_or_global_unsaved;
_update_title();
@@ -634,6 +634,10 @@ void EditorNode::_notification(int p_what) {
set_addon_plugin_enabled(addons[i], true);
}
_initializing_plugins = false;
+
+ if (!pending_addons.is_empty()) {
+ EditorFileSystem::get_singleton()->connect("script_classes_updated", callable_mp(this, &EditorNode::_enable_pending_addons));
+ }
}
RenderingServer::get_singleton()->viewport_set_disable_2d(get_scene_root()->get_viewport_rid(), true);
@@ -1130,7 +1134,7 @@ void EditorNode::_version_button_pressed() {
}
void EditorNode::_update_undo_redo_allowed() {
- Ref<EditorUndoRedoManager> undo_redo = get_undo_redo();
+ EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
file_menu->set_item_disabled(file_menu->get_item_index(EDIT_UNDO), !undo_redo->has_undo());
file_menu->set_item_disabled(file_menu->get_item_index(EDIT_REDO), !undo_redo->has_redo());
}
@@ -1682,7 +1686,7 @@ int EditorNode::_save_external_resources() {
saved++;
}
- get_undo_redo()->set_history_as_saved(EditorUndoRedoManager::GLOBAL_HISTORY);
+ EditorUndoRedoManager::get_singleton()->set_history_as_saved(EditorUndoRedoManager::GLOBAL_HISTORY);
return saved;
}
@@ -1859,7 +1863,7 @@ void EditorNode::_mark_unsaved_scenes() {
String path = node->get_scene_file_path();
if (!path.is_empty() && !FileAccess::exists(path)) {
// Mark scene tab as unsaved if the file is gone.
- get_undo_redo()->set_history_as_unsaved(editor_data.get_scene_history_id(i));
+ EditorUndoRedoManager::get_singleton()->set_history_as_unsaved(editor_data.get_scene_history_id(i));
}
}
@@ -2074,51 +2078,55 @@ bool EditorNode::_is_class_editor_disabled_by_feature_profile(const StringName &
return false;
}
-void EditorNode::edit_item(Object *p_object) {
+void EditorNode::edit_item(Object *p_object, Object *p_editing_owner) {
+ ERR_FAIL_NULL(p_editing_owner);
+
if (p_object && _is_class_editor_disabled_by_feature_profile(p_object->get_class())) {
return;
}
- Vector<EditorPlugin *> top_plugins = editor_plugins_over->get_plugins_list();
Vector<EditorPlugin *> item_plugins;
if (p_object) {
item_plugins = editor_data.get_subeditors(p_object);
}
if (!item_plugins.is_empty()) {
- bool same = true;
- if (item_plugins.size() == top_plugins.size()) {
- for (int i = 0; i < item_plugins.size(); i++) {
- if (item_plugins[i] != top_plugins[i]) {
- same = false;
- }
+ ObjectID owner_id = p_editing_owner->get_instance_id();
+
+ for (EditorPlugin *plugin : active_plugins[owner_id]) {
+ if (!item_plugins.has(plugin)) {
+ plugin->make_visible(false);
+ plugin->edit(nullptr);
}
- } else {
- same = false;
}
- if (!same) {
- _display_top_editors(false);
- _set_top_editors(item_plugins);
+ for (EditorPlugin *plugin : item_plugins) {
+ for (KeyValue<ObjectID, HashSet<EditorPlugin *>> &kv : active_plugins) {
+ if (kv.key != owner_id) {
+ EditorPropertyResource *epres = Object::cast_to<EditorPropertyResource>(ObjectDB::get_instance(kv.key));
+ if (epres && kv.value.has(plugin)) {
+ // If it's resource property editing the same resource type, fold it.
+ epres->fold_resource();
+ }
+ kv.value.erase(plugin);
+ }
+ }
+ active_plugins[owner_id].insert(plugin);
+ plugin->edit(p_object);
+ plugin->make_visible(true);
}
- _set_editing_top_editors(p_object);
- _display_top_editors(true);
- } else if (!top_plugins.is_empty()) {
- hide_top_editors();
+ } else {
+ hide_unused_editors(p_editing_owner);
}
}
-void EditorNode::edit_item_resource(Ref<Resource> p_resource) {
- edit_item(p_resource.ptr());
-}
-
void EditorNode::push_item(Object *p_object, const String &p_property, bool p_inspector_only) {
if (!p_object) {
InspectorDock::get_inspector_singleton()->edit(nullptr);
NodeDock::get_singleton()->set_node(nullptr);
SceneTreeDock::get_singleton()->set_selected(nullptr);
InspectorDock::get_singleton()->update(nullptr);
- _display_top_editors(false);
+ hide_unused_editors();
return;
}
@@ -2146,22 +2154,34 @@ void EditorNode::_save_default_environment() {
}
}
-void EditorNode::hide_top_editors() {
- _display_top_editors(false);
-
- editor_plugins_over->clear();
-}
-
-void EditorNode::_display_top_editors(bool p_display) {
- editor_plugins_over->make_visible(p_display);
-}
-
-void EditorNode::_set_top_editors(Vector<EditorPlugin *> p_editor_plugins_over) {
- editor_plugins_over->set_plugins_list(p_editor_plugins_over);
-}
+void EditorNode::hide_unused_editors(const Object *p_editing_owner) {
+ if (p_editing_owner) {
+ const ObjectID id = p_editing_owner->get_instance_id();
+ for (EditorPlugin *plugin : active_plugins[id]) {
+ plugin->make_visible(false);
+ plugin->edit(nullptr);
+ editor_plugins_over->remove_plugin(plugin);
+ }
+ active_plugins.erase(id);
+ } else {
+ // If no editing owner is provided, this method will go over all owners and check if they are valid.
+ // This is to sweep properties that were removed from the inspector.
+ List<ObjectID> to_remove;
+ for (KeyValue<ObjectID, HashSet<EditorPlugin *>> &kv : active_plugins) {
+ if (!ObjectDB::get_instance(kv.key)) {
+ to_remove.push_back(kv.key);
+ for (EditorPlugin *plugin : kv.value) {
+ plugin->make_visible(false);
+ plugin->edit(nullptr);
+ editor_plugins_over->remove_plugin(plugin);
+ }
+ }
+ }
-void EditorNode::_set_editing_top_editors(Object *p_current_object) {
- editor_plugins_over->edit(p_current_object);
+ for (const ObjectID &id : to_remove) {
+ active_plugins.erase(id);
+ }
+ }
}
static bool overrides_external_editor(Object *p_object) {
@@ -2195,7 +2215,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
NodeDock::get_singleton()->set_node(nullptr);
InspectorDock::get_singleton()->update(nullptr);
- _display_top_editors(false);
+ hide_unused_editors();
return;
}
@@ -2323,6 +2343,9 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
InspectorDock::get_inspector_singleton()->set_use_folding(!disable_folding);
}
+ Object *editor_owner = is_node ? (Object *)SceneTreeDock::get_singleton() : is_resource ? (Object *)InspectorDock::get_inspector_singleton()
+ : (Object *)this;
+
// Take care of the main editor plugin.
if (!inspector_only) {
@@ -2339,6 +2362,7 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
}
}
+ ObjectID editor_owner_id = editor_owner->get_instance_id();
if (main_plugin && !skip_main_plugin) {
// Special case if use of external editor is true.
Resource *current_res = Object::cast_to<Resource>(current_obj);
@@ -2349,15 +2373,22 @@ void EditorNode::_edit_current(bool p_skip_foreign) {
}
else if (main_plugin != editor_plugin_screen && (!ScriptEditor::get_singleton() || !ScriptEditor::get_singleton()->is_visible_in_tree() || ScriptEditor::get_singleton()->can_take_away_focus())) {
+ // Unedit previous plugin.
+ editor_plugin_screen->edit(nullptr);
+ active_plugins[editor_owner_id].erase(editor_plugin_screen);
// Update screen main_plugin.
editor_select(plugin_index);
main_plugin->edit(current_obj);
} else {
editor_plugin_screen->edit(current_obj);
}
+ is_main_screen_editing = true;
+ } else if (!main_plugin && editor_plugin_screen && is_main_screen_editing) {
+ editor_plugin_screen->edit(nullptr);
+ is_main_screen_editing = false;
}
- edit_item(current_obj);
+ edit_item(current_obj, editor_owner);
}
InspectorDock::get_singleton()->update(current_obj);
@@ -2746,9 +2777,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
if ((int)Input::get_singleton()->get_mouse_button_mask() & 0x7) {
log->add_message(TTR("Can't undo while mouse buttons are pressed."), EditorLog::MSG_TYPE_EDITOR);
} else {
- String action = editor_data.get_undo_redo()->get_current_action_name();
- int id = editor_data.get_undo_redo()->get_current_action_history_id();
- if (!editor_data.get_undo_redo()->undo()) {
+ EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
+ String action = undo_redo->get_current_action_name();
+ int id = undo_redo->get_current_action_history_id();
+ if (!undo_redo->undo()) {
log->add_message(TTR("Nothing to undo."), EditorLog::MSG_TYPE_EDITOR);
} else if (!action.is_empty()) {
switch (id) {
@@ -2765,18 +2797,19 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
}
} break;
case EDIT_REDO: {
+ EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
if ((int)Input::get_singleton()->get_mouse_button_mask() & 0x7) {
log->add_message(TTR("Can't redo while mouse buttons are pressed."), EditorLog::MSG_TYPE_EDITOR);
} else {
- if (!editor_data.get_undo_redo()->redo()) {
+ if (!undo_redo->redo()) {
log->add_message(TTR("Nothing to redo."), EditorLog::MSG_TYPE_EDITOR);
} else {
- String action = editor_data.get_undo_redo()->get_current_action_name();
+ String action = undo_redo->get_current_action_name();
if (action.is_empty()) {
break;
}
- switch (editor_data.get_undo_redo()->get_current_action_history_id()) {
+ switch (undo_redo->get_current_action_history_id()) {
case EditorUndoRedoManager::GLOBAL_HISTORY:
log->add_message(vformat(TTR("Global Redo: %s"), action), EditorLog::MSG_TYPE_EDITOR);
break;
@@ -2819,7 +2852,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
ERR_PRINT("Failed to load scene");
}
editor_data.move_edited_scene_to_index(cur_idx);
- get_undo_redo()->clear_history(false, editor_data.get_current_edited_scene_history_id());
+ EditorUndoRedoManager::get_singleton()->clear_history(false, editor_data.get_current_edited_scene_history_id());
scene_tabs->set_current_tab(cur_idx);
} break;
@@ -2911,7 +2944,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case RELOAD_CURRENT_PROJECT: {
if (!p_confirmed) {
bool save_each = EDITOR_GET("interface/editor/save_each_scene_on_quit");
- if (_next_unsaved_scene(!save_each) == -1 && !get_undo_redo()->is_history_unsaved(EditorUndoRedoManager::GLOBAL_HISTORY)) {
+ if (_next_unsaved_scene(!save_each) == -1 && !EditorUndoRedoManager::get_singleton()->is_history_unsaved(EditorUndoRedoManager::GLOBAL_HISTORY)) {
_discard_changes();
break;
} else {
@@ -3150,7 +3183,7 @@ int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) {
if (!editor_data.get_edited_scene_root(i)) {
continue;
}
- bool unsaved = get_undo_redo()->is_history_unsaved(editor_data.get_scene_history_id(i));
+ bool unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(editor_data.get_scene_history_id(i));
if (unsaved) {
String scene_filename = editor_data.get_edited_scene_root(i)->get_scene_file_path();
if (p_valid_filename && scene_filename.length() == 0) {
@@ -3471,6 +3504,12 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled,
// Errors in the script cause the base_type to be an empty StringName.
if (scr->get_instance_base_type() == StringName()) {
+ if (_initializing_plugins) {
+ // However, if it happens during initialization, waiting for file scan might help.
+ pending_addons.push_back(p_addon);
+ return;
+ }
+
show_warning(vformat(TTR("Unable to load addon script from path: '%s'. This might be due to a code error in that script.\nDisabling the addon at '%s' to prevent further errors."), script_path, addon_path));
_remove_plugin_from_enabled(addon_path);
return;
@@ -3614,12 +3653,12 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
if (get_edited_scene()) {
if (current_tab < 2) {
- // Use heuristic instead.
- int n2d = 0, n3d = 0;
- _find_node_types(get_edited_scene(), n2d, n3d);
- if (n2d > n3d) {
+ Node *editor_node = SceneTreeDock::get_singleton()->get_tree_editor()->get_selected();
+ editor_node = editor_node == nullptr ? get_edited_scene() : editor_node;
+
+ if (Object::cast_to<Node2D>(editor_node) || Object::cast_to<Control>(editor_node)) {
editor_select(EDITOR_2D);
- } else if (n3d > n2d) {
+ } else if (Object::cast_to<Node3D>(editor_node)) {
editor_select(EDITOR_3D);
}
}
@@ -3659,7 +3698,7 @@ void EditorNode::set_current_scene(int p_idx) {
editor_folding.load_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx));
}
- get_undo_redo()->clear_history(false, editor_data.get_scene_history_id(p_idx));
+ EditorUndoRedoManager::get_singleton()->clear_history(false, editor_data.get_scene_history_id(p_idx));
}
changing_scene = true;
@@ -3700,11 +3739,12 @@ void EditorNode::set_current_scene(int p_idx) {
call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); // Do after everything else is done setting up.
}
-void EditorNode::setup_color_picker(ColorPicker *picker) {
+void EditorNode::setup_color_picker(ColorPicker *p_picker) {
+ p_picker->set_editor_settings(EditorSettings::get_singleton());
int default_color_mode = EDITOR_GET("interface/inspector/default_color_picker_mode");
int picker_shape = EDITOR_GET("interface/inspector/default_color_picker_shape");
- picker->set_color_mode((ColorPicker::ColorModeType)default_color_mode);
- picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape);
+ p_picker->set_color_mode((ColorPicker::ColorModeType)default_color_mode);
+ p_picker->set_picker_shape((ColorPicker::PickerShapeType)picker_shape);
}
bool EditorNode::is_scene_open(const String &p_path) {
@@ -3726,7 +3766,7 @@ int EditorNode::new_scene() {
// Remove placeholder empty scene.
if (editor_data.get_edited_scene_count() > 1) {
for (int i = 0; i < editor_data.get_edited_scene_count() - 1; i++) {
- bool unsaved = get_undo_redo()->is_history_unsaved(editor_data.get_scene_history_id(i));
+ bool unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(editor_data.get_scene_history_id(i));
if (!unsaved && editor_data.get_scene_path(i).is_empty() && editor_data.get_edited_scene_root(i) == nullptr) {
editor_data.remove_scene(i);
idx--;
@@ -3951,10 +3991,6 @@ void EditorNode::request_instantiate_scenes(const Vector<String> &p_files) {
SceneTreeDock::get_singleton()->instantiate_scenes(p_files);
}
-Ref<EditorUndoRedoManager> &EditorNode::get_undo_redo() {
- return singleton->editor_data.get_undo_redo();
-}
-
void EditorNode::_inherit_request(String p_file) {
current_menu_option = FILE_NEW_INHERITED_SCENE;
_dialog_action(p_file);
@@ -4380,6 +4416,13 @@ void EditorNode::_build_icon_type_cache() {
}
}
+void EditorNode::_enable_pending_addons() {
+ for (uint32_t i = 0; i < pending_addons.size(); i++) {
+ set_addon_plugin_enabled(pending_addons[i], true);
+ }
+ pending_addons.clear();
+}
+
void EditorNode::_file_dialog_register(FileDialog *p_dialog) {
singleton->file_dialogs.insert(p_dialog);
}
@@ -5067,8 +5110,8 @@ bool EditorNode::ensure_main_scene(bool p_from_native) {
return true;
}
-Error EditorNode::run_play_native(int p_idx, int p_platform) {
- return run_native->run_native(p_idx, p_platform);
+Error EditorNode::run_play_native(int p_id) {
+ return run_native->run_native(p_id);
}
void EditorNode::run_play() {
@@ -5224,7 +5267,7 @@ void EditorNode::_scene_tab_closed(int p_tab, int option) {
return;
}
- bool unsaved = get_undo_redo()->is_history_unsaved(editor_data.get_scene_history_id(p_tab));
+ bool unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(editor_data.get_scene_history_id(p_tab));
if (unsaved) {
save_confirmation->set_ok_button_text(TTR("Save & Close"));
save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), !scene->get_scene_file_path().is_empty() ? scene->get_scene_file_path() : "unsaved scene"));
@@ -5723,7 +5766,7 @@ void EditorNode::reload_scene(const String &p_path) {
if (scene_idx == -1) {
if (get_edited_scene()) {
// Scene is not open, so at it might be instantiated. We'll refresh the whole scene later.
- editor_data.get_undo_redo()->clear_history(false, editor_data.get_current_edited_scene_history_id());
+ EditorUndoRedoManager::get_singleton()->clear_history(false, editor_data.get_current_edited_scene_history_id());
}
return;
}
@@ -5739,7 +5782,7 @@ void EditorNode::reload_scene(const String &p_path) {
// Adjust index so tab is back a the previous position.
editor_data.move_edited_scene_to_index(scene_idx);
- get_undo_redo()->clear_history(false, editor_data.get_scene_history_id(scene_idx));
+ EditorUndoRedoManager::get_singleton()->clear_history(false, editor_data.get_scene_history_id(scene_idx));
// Recover the tab.
scene_tabs->set_current_tab(current_tab);
@@ -6057,8 +6100,8 @@ EditorNode::EditorNode() {
singleton = this;
- get_undo_redo()->connect("version_changed", callable_mp(this, &EditorNode::_update_undo_redo_allowed));
- get_undo_redo()->connect("history_changed", callable_mp(this, &EditorNode::_update_undo_redo_allowed));
+ EditorUndoRedoManager::get_singleton()->connect("version_changed", callable_mp(this, &EditorNode::_update_undo_redo_allowed));
+ EditorUndoRedoManager::get_singleton()->connect("history_changed", callable_mp(this, &EditorNode::_update_undo_redo_allowed));
TranslationServer::get_singleton()->set_enabled(false);
// Load settings.
@@ -6901,7 +6944,7 @@ EditorNode::EditorNode() {
_reset_play_buttons();
- ED_SHORTCUT_AND_COMMAND("editor/run_specific_scene", TTR("Run Specific Scene"), KeyModifierMask::META | KeyModifierMask::SHIFT | Key::F5);
+ ED_SHORTCUT_AND_COMMAND("editor/run_specific_scene", TTR("Run Specific Scene"), KeyModifierMask::CTRL | KeyModifierMask::SHIFT | Key::F5);
ED_SHORTCUT_OVERRIDE("editor/run_specific_scene", "macos", KeyModifierMask::META | KeyModifierMask::SHIFT | Key::R);
play_custom_scene_button->set_shortcut(ED_GET_SHORTCUT("editor/run_specific_scene"));
@@ -7053,8 +7096,8 @@ EditorNode::EditorNode() {
right_r_vsplit->hide();
// Add some offsets to left_r and main hsplits to make LEFT_R and RIGHT_L docks wider than minsize.
- left_r_hsplit->set_split_offset(70 * EDSCALE);
- main_hsplit->set_split_offset(-70 * EDSCALE);
+ left_r_hsplit->set_split_offset(270 * EDSCALE);
+ main_hsplit->set_split_offset(-270 * EDSCALE);
// Define corresponding default layout.
@@ -7069,8 +7112,8 @@ EditorNode::EditorNode() {
default_layout->set_value(docks_section, "dock_split_" + itos(i + 1), 0);
}
default_layout->set_value(docks_section, "dock_hsplit_1", 0);
- default_layout->set_value(docks_section, "dock_hsplit_2", 70 * EDSCALE);
- default_layout->set_value(docks_section, "dock_hsplit_3", -70 * EDSCALE);
+ default_layout->set_value(docks_section, "dock_hsplit_2", 270 * EDSCALE);
+ default_layout->set_value(docks_section, "dock_hsplit_3", -270 * EDSCALE);
default_layout->set_value(docks_section, "dock_hsplit_4", 0);
_update_layouts_menu();
@@ -7385,7 +7428,6 @@ EditorNode::EditorNode() {
_update_recent_scenes();
- editor_data.restore_editor_global_states();
set_process_shortcut_input(true);
load_errors = memnew(RichTextLabel);