diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 945372fbdf4..56d5397528f 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -56,7 +56,6 @@ #include "scene/gui/popup.h" #include "scene/gui/rich_text_label.h" #include "scene/gui/split_container.h" -#include "scene/gui/tab_bar.h" #include "scene/gui/tab_container.h" #include "scene/main/window.h" #include "scene/property_utils.h" @@ -105,6 +104,7 @@ #include "editor/filesystem_dock.h" #include "editor/gui/editor_file_dialog.h" #include "editor/gui/editor_run_bar.h" +#include "editor/gui/editor_scene_tabs.h" #include "editor/gui/editor_title_bar.h" #include "editor/gui/editor_toaster.h" #include "editor/history_dock.h" @@ -271,90 +271,6 @@ void EditorNode::disambiguate_filenames(const Vector p_full_paths, Vecto } } -// TODO: This REALLY should be done in a better way than replacing all tabs after almost EVERY action. -void EditorNode::_update_scene_tabs() { - bool show_rb = EDITOR_GET("interface/scene_tabs/show_script_button"); - - if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) { - DisplayServer::get_singleton()->global_menu_clear("_dock"); - } - - // Get all scene names, which may be ambiguous. - Vector disambiguated_scene_names; - Vector full_path_names; - for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { - disambiguated_scene_names.append(editor_data.get_scene_title(i)); - full_path_names.append(editor_data.get_scene_path(i)); - } - - disambiguate_filenames(full_path_names, disambiguated_scene_names); - - // Workaround to ignore the tab_changed signal from the first added tab. - scene_tabs->disconnect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed)); - - scene_tabs->clear_tabs(); - Ref script_icon = gui_base->get_theme_icon(SNAME("Script"), SNAME("EditorIcons")); - for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { - Node *type_node = editor_data.get_edited_scene_root(i); - Ref icon; - if (type_node) { - icon = EditorNode::get_singleton()->get_object_icon(type_node, "Node"); - } - - 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)) { - DisplayServer::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), callable_mp(this, &EditorNode::_global_menu_scene), Callable(), i); - } - - if (show_rb && editor_data.get_scene_root_script(i).is_valid()) { - scene_tabs->set_tab_button_icon(i, script_icon); - } - } - - if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) { - DisplayServer::get_singleton()->global_menu_add_separator("_dock"); - DisplayServer::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), callable_mp(this, &EditorNode::_global_menu_new_window)); - } - - if (scene_tabs->get_tab_count() > 0) { - scene_tabs->set_current_tab(editor_data.get_edited_scene()); - } - - const Size2 add_button_size = Size2(scene_tab_add->get_size().x, scene_tabs->get_size().y); - if (scene_tabs->get_offset_buttons_visible()) { - // Move the add button to a fixed position. - if (scene_tab_add->get_parent() == scene_tabs) { - scene_tabs->remove_child(scene_tab_add); - scene_tab_add_ph->add_child(scene_tab_add); - scene_tab_add->set_rect(Rect2(Point2(), add_button_size)); - } - } else { - // Move the add button to be after the last tab. - if (scene_tab_add->get_parent() == scene_tab_add_ph) { - scene_tab_add_ph->remove_child(scene_tab_add); - scene_tabs->add_child(scene_tab_add); - } - - if (scene_tabs->get_tab_count() == 0) { - scene_tab_add->set_rect(Rect2(Point2(), add_button_size)); - return; - } - - Rect2 last_tab = scene_tabs->get_tab_rect(scene_tabs->get_tab_count() - 1); - int hsep = scene_tabs->get_theme_constant(SNAME("h_separation")); - if (scene_tabs->is_layout_rtl()) { - scene_tab_add->set_rect(Rect2(Point2(last_tab.position.x - add_button_size.x - hsep, last_tab.position.y), add_button_size)); - } else { - scene_tab_add->set_rect(Rect2(Point2(last_tab.position.x + last_tab.size.width + hsep, last_tab.position.y), add_button_size)); - } - } - - // Reconnect after everything is done. - scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed)); -} - void EditorNode::_version_control_menu_option(int p_idx) { switch (vcs_actions_menu->get_item_id(p_idx)) { case RUN_VCS_METADATA: { @@ -391,16 +307,6 @@ void EditorNode::shortcut_input(const Ref &p_event) { if ((k.is_valid() && k->is_pressed() && !k->is_echo()) || Object::cast_to(*p_event)) { EditorPlugin *old_editor = editor_plugin_screen; - if (ED_IS_SHORTCUT("editor/next_tab", p_event)) { - int next_tab = editor_data.get_edited_scene() + 1; - next_tab %= editor_data.get_edited_scene_count(); - _scene_tab_changed(next_tab); - } - if (ED_IS_SHORTCUT("editor/prev_tab", p_event)) { - int next_tab = editor_data.get_edited_scene() - 1; - next_tab = next_tab >= 0 ? next_tab : editor_data.get_edited_scene_count() - 1; - _scene_tab_changed(next_tab); - } if (ED_IS_SHORTCUT("editor/filter_files", p_event)) { FileSystemDock::get_singleton()->focus_on_filter(); } @@ -562,7 +468,7 @@ void EditorNode::_notification(int p_what) { } if (editor_data.is_scene_changed(-1)) { - _update_scene_tabs(); + scene_tabs->update_scene_tabs(); } // Update the animation frame of the update spinner. @@ -707,7 +613,6 @@ void EditorNode::_notification(int p_what) { } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - scene_tabs->set_tab_close_display_policy((TabBar::CloseButtonDisplayPolicy)EDITOR_GET("interface/scene_tabs/display_close_button").operator int()); FileDialog::set_default_show_hidden_files(EDITOR_GET("filesystem/file_dialog/show_hidden_files")); EditorFileDialog::set_default_show_hidden_files(EDITOR_GET("filesystem/file_dialog/show_hidden_files")); EditorFileDialog::set_default_display_mode((EditorFileDialog::DisplayMode)EDITOR_GET("filesystem/file_dialog/display_mode").operator int()); @@ -737,17 +642,10 @@ void EditorNode::_notification(int p_what) { main_vbox->add_theme_constant_override("separation", gui_base->get_theme_constant(SNAME("top_bar_separation"), SNAME("Editor"))); scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Content"), SNAME("EditorStyles"))); bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), SNAME("EditorStyles"))); - tabbar_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("tabbar_background"), SNAME("TabContainer"))); - - scene_tabs->add_theme_constant_override("icon_max_width", gui_base->get_theme_constant(SNAME("class_icon_size"), SNAME("Editor"))); - scene_tab_add_ph->set_custom_minimum_size(scene_tab_add->get_minimum_size()); - main_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); } - scene_tabs->set_max_tab_width(int(EDITOR_GET("interface/scene_tabs/maximum_width")) * EDSCALE); - _update_scene_tabs(); - + scene_tabs->update_scene_tabs(); recent_scenes->reset_size(); // Update debugger area. @@ -772,7 +670,6 @@ void EditorNode::_notification(int p_what) { prev_scene->set_icon(gui_base->get_theme_icon(SNAME("PrevScene"), SNAME("EditorIcons"))); distraction_free->set_icon(gui_base->get_theme_icon(SNAME("DistractionFree"), SNAME("EditorIcons"))); - scene_tab_add->set_icon(gui_base->get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); bottom_panel_raise->set_icon(gui_base->get_theme_icon(SNAME("ExpandBottomDock"), SNAME("EditorIcons"))); @@ -1131,8 +1028,8 @@ void EditorNode::_reload_modified_scenes() { } } - set_current_scene(current_idx); - _update_scene_tabs(); + _set_current_scene(current_idx); + scene_tabs->update_scene_tabs(); disk_changed->hide(); } @@ -1378,6 +1275,10 @@ void EditorNode::_menu_confirm_current() { _menu_option_confirm(current_menu_option, true); } +void EditorNode::trigger_menu_option(int p_option, bool p_confirmed) { + _menu_option_confirm(p_option, p_confirmed); +} + void EditorNode::_dialog_display_save_error(String p_file, Error p_error) { if (p_error) { switch (p_error) { @@ -1813,7 +1714,7 @@ void EditorNode::_save_scene(String p_file, int idx) { editor_folding.save_scene_folding(scene, p_file); _update_title(); - _update_scene_tabs(); + scene_tabs->update_scene_tabs(); } else { _dialog_display_save_error(p_file, err); } @@ -1928,7 +1829,7 @@ void EditorNode::_mark_unsaved_scenes() { } _update_title(); - _update_scene_tabs(); + scene_tabs->update_scene_tabs(); } void EditorNode::_dialog_action(String p_file) { @@ -2268,7 +2169,8 @@ void EditorNode::_edit_current(bool p_skip_foreign) { Ref res = Object::cast_to(current_obj); if (p_skip_foreign && res.is_valid()) { - if (res->get_path().find("::") > -1 && res->get_path().get_slice("::", 0) != editor_data.get_scene_path(get_current_tab())) { + const int current_tab = scene_tabs->get_current_tab(); + if (res->get_path().find("::") > -1 && res->get_path().get_slice("::", 0) != editor_data.get_scene_path(current_tab)) { // Trying to edit resource that belongs to another scene; abort. current_obj = nullptr; } @@ -3101,7 +3003,7 @@ void EditorNode::_discard_changes(const String &p_str) { // Don't close tabs when exiting the editor (required for "restore_scenes_on_load" setting). if (!_is_closing_editor()) { _remove_scene(tab_closing_idx); - _update_scene_tabs(); + scene_tabs->update_scene_tabs(); } _proceed_closing_scene_tabs(); } break; @@ -3439,11 +3341,11 @@ void EditorNode::_remove_edited_scene(bool p_change_tab) { } if (p_change_tab) { - _scene_tab_changed(new_index); + _set_current_scene(new_index); } editor_data.remove_scene(old_index); _update_title(); - _update_scene_tabs(); + scene_tabs->update_scene_tabs(); } void EditorNode::_remove_scene(int index, bool p_change_tab) { @@ -3565,7 +3467,15 @@ bool EditorNode::is_changing_scene() const { return changing_scene; } -void EditorNode::set_current_scene(int p_idx) { +void EditorNode::_set_current_scene(int p_idx) { + if (p_idx == editor_data.get_edited_scene()) { + return; // Pointless. + } + + _set_current_scene_nocheck(p_idx); +} + +void EditorNode::_set_current_scene_nocheck(int p_idx) { // Save the folding in case the scene gets reloaded. if (editor_data.get_scene_path(p_idx) != "" && editor_data.get_edited_scene_root(p_idx)) { editor_folding.save_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx)); @@ -3612,7 +3522,7 @@ void EditorNode::set_current_scene(int p_idx) { _edit_current(true); _update_title(); - _update_scene_tabs(); + scene_tabs->update_scene_tabs(); if (tabs_to_close.is_empty()) { call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); // Do after everything else is done setting up. @@ -3655,9 +3565,9 @@ int EditorNode::new_scene() { } idx = MAX(idx, 0); - _scene_tab_changed(idx); + _set_current_scene(idx); editor_data.clear_editor_states(); - _update_scene_tabs(); + scene_tabs->update_scene_tabs(); return idx; } @@ -3670,7 +3580,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b if (!p_set_inherited) { for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { if (editor_data.get_scene_path(i) == p_scene) { - _scene_tab_changed(i); + _set_current_scene(i); return OK; } } @@ -3701,10 +3611,10 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b if (!editor_data.get_edited_scene_root() && editor_data.get_edited_scene_count() == 2) { _remove_edited_scene(); - } else if (!p_silent_change_tab) { - _scene_tab_changed(idx); + } else if (p_silent_change_tab) { + _set_current_scene_nocheck(idx); } else { - set_current_scene(idx); + _set_current_scene(idx); } dependency_errors.clear(); @@ -3716,7 +3626,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b opening_prev = false; if (prev != -1) { - set_current_scene(prev); + _set_current_scene(prev); editor_data.remove_scene(idx); } return ERR_FILE_NOT_FOUND; @@ -3732,7 +3642,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b opening_prev = false; if (prev != -1) { - set_current_scene(prev); + _set_current_scene(prev); editor_data.remove_scene(idx); } return ERR_FILE_MISSING_DEPENDENCIES; @@ -3768,7 +3678,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b _dialog_display_load_error(lpath, ERR_FILE_CORRUPT); opening_prev = false; if (prev != -1) { - set_current_scene(prev); + _set_current_scene(prev); editor_data.remove_scene(idx); } return ERR_FILE_CORRUPT; @@ -3794,7 +3704,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b } _update_title(); - _update_scene_tabs(); + scene_tabs->update_scene_tabs(); _add_to_recent_scenes(lpath); if (editor_folding.has_folding_data(lpath)) { @@ -3989,6 +3899,10 @@ void EditorNode::open_request(const String &p_path) { load_scene(p_path); // As it will be opened in separate tab. } +bool EditorNode::has_previous_scenes() const { + return !previous_scenes.is_empty(); +} + void EditorNode::edit_foreign_resource(Ref p_resource) { load_scene(p_resource->get_path().get_slice("::", 0)); InspectorDock::get_singleton()->call_deferred("edit_resource", p_resource); @@ -5399,7 +5313,7 @@ void EditorNode::_load_open_scenes_from_config(Ref p_layout) { String current_scene = p_layout->get_value(EDITOR_NODE_CONFIG_SECTION, "current_scene"); int current_scene_idx = scenes.find(current_scene); if (current_scene_idx >= 0) { - set_current_scene(current_scene_idx); + _set_current_scene(current_scene_idx); } } @@ -5491,14 +5405,6 @@ void EditorNode::cleanup() { _init_callbacks.clear(); } -int EditorNode::get_current_tab() { - return scene_tabs->get_current_tab(); -} - -void EditorNode::set_current_tab(int p_tab) { - scene_tabs->set_current_tab(p_tab); -} - void EditorNode::_update_layouts_menu() { editor_layouts->clear(); overridden_default_layout = -1; @@ -5563,13 +5469,6 @@ void EditorNode::_layout_menu_option(int p_id) { } } -void EditorNode::_scene_tab_script_edited(int p_tab) { - Ref