diff options
Diffstat (limited to 'editor/editor_node.cpp')
-rw-r--r-- | editor/editor_node.cpp | 204 |
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); |