Path: blob/master/editor/scene/editor_scene_tabs.cpp
20951 views
/**************************************************************************/1/* editor_scene_tabs.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "editor_scene_tabs.h"3132#include "core/config/project_settings.h"33#include "core/io/resource_loader.h"34#include "editor/docks/inspector_dock.h"35#include "editor/editor_main_screen.h"36#include "editor/editor_node.h"37#include "editor/editor_string_names.h"38#include "editor/editor_undo_redo_manager.h"39#include "editor/inspector/editor_context_menu_plugin.h"40#include "editor/inspector/editor_resource_preview.h"41#include "editor/run/editor_run_bar.h"42#include "editor/settings/editor_settings.h"43#include "editor/themes/editor_scale.h"44#include "scene/gui/box_container.h"45#include "scene/gui/button.h"46#include "scene/gui/menu_button.h"47#include "scene/gui/panel.h"48#include "scene/gui/panel_container.h"49#include "scene/gui/popup_menu.h"50#include "scene/gui/tab_bar.h"51#include "scene/gui/texture_rect.h"5253void EditorSceneTabs::_notification(int p_what) {54switch (p_what) {55case NOTIFICATION_THEME_CHANGED: {56tabbar_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("tabbar_background"), SNAME("TabContainer")));57scene_tabs->add_theme_constant_override("icon_max_width", get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor)));5859scene_list->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl")));6061scene_tab_add->set_button_icon(get_editor_theme_icon(SNAME("Add")));62scene_tab_add->add_theme_color_override("icon_normal_color", Color(0.6f, 0.6f, 0.6f, 0.8f));6364scene_tab_add_ph->set_custom_minimum_size(scene_tab_add->get_minimum_size());65} break;6667case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {68if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/scene_tabs")) {69scene_tabs->set_tab_close_display_policy((TabBar::CloseButtonDisplayPolicy)EDITOR_GET("interface/scene_tabs/display_close_button").operator int());70scene_tabs->set_max_tab_width(int(EDITOR_GET("interface/scene_tabs/maximum_width")) * EDSCALE);71_scene_tabs_resized();72}73} break;7475case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:76case NOTIFICATION_TRANSLATION_CHANGED: {77_scene_tabs_resized();78} break;79}80}8182void EditorSceneTabs::_scene_tab_changed(int p_tab) {83tab_preview_panel->hide();8485emit_signal("tab_changed", p_tab);86}8788void EditorSceneTabs::_scene_tab_script_edited(int p_tab) {89Ref<Script> scr = EditorNode::get_editor_data().get_scene_root_script(p_tab);90if (scr.is_valid()) {91InspectorDock::get_singleton()->edit_resource(scr);92}93}9495void EditorSceneTabs::_scene_tab_closed(int p_tab) {96emit_signal("tab_closed", p_tab);97}9899void EditorSceneTabs::_scene_tab_hovered(int p_tab) {100if (!bool(EDITOR_GET("interface/scene_tabs/show_thumbnail_on_hover"))) {101return;102}103104// Currently the tab previews are displayed under the running game process when embed.105// Right now, the easiest technique to fix that is to prevent displaying the tab preview106// when the user is in the Game View.107if (EditorNode::get_singleton()->get_editor_main_screen()->get_selected_index() == EditorMainScreen::EDITOR_GAME && EditorRunBar::get_singleton()->is_playing()) {108return;109}110111int current_tab = scene_tabs->get_current_tab();112113if (p_tab == current_tab || p_tab < 0) {114tab_preview_panel->hide();115} else {116String path = EditorNode::get_editor_data().get_scene_path(p_tab);117if (!path.is_empty()) {118EditorResourcePreview::get_singleton()->queue_resource_preview(path, callable_mp(this, &EditorSceneTabs::_tab_preview_done).bind(p_tab));119}120}121}122123void EditorSceneTabs::_scene_tab_exit() {124tab_preview_panel->hide();125}126127void EditorSceneTabs::_scene_tab_input(const Ref<InputEvent> &p_input) {128Ref<InputEventMouseButton> mb = p_input;129130if (mb.is_valid()) {131if (scene_tabs->get_hovered_tab() < 0 && mb->get_button_index() == MouseButton::LEFT && mb->is_double_click()) {132int tab_buttons = 0;133if (scene_tabs->get_offset_buttons_visible()) {134tab_buttons = get_theme_icon(SNAME("increment"), SNAME("TabBar"))->get_width() + get_theme_icon(SNAME("decrement"), SNAME("TabBar"))->get_width();135}136137if ((is_layout_rtl() && mb->get_position().x > tab_buttons) || (!is_layout_rtl() && mb->get_position().x < scene_tabs->get_size().width - tab_buttons)) {138EditorNode::get_singleton()->trigger_menu_option(EditorNode::SCENE_NEW_SCENE, true);139}140} else if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) {141// Context menu.142_update_context_menu();143144scene_tabs_context_menu->set_position(scene_tabs->get_screen_position() + mb->get_position());145scene_tabs_context_menu->reset_size();146scene_tabs_context_menu->popup();147}148}149}150151void EditorSceneTabs::unhandled_key_input(const Ref<InputEvent> &p_event) {152if (!tab_preview_panel->is_visible()) {153return;154}155156Ref<InputEventKey> k = p_event;157if (k.is_valid() && k->is_action_pressed(SNAME("ui_cancel"), false, true)) {158tab_preview_panel->hide();159}160}161162void EditorSceneTabs::_reposition_active_tab(int p_to_index) {163EditorNode::get_editor_data().move_edited_scene_to_index(p_to_index);164update_scene_tabs();165}166167void EditorSceneTabs::_update_context_menu() {168#define DISABLE_LAST_OPTION_IF(m_condition) \169if (m_condition) { \170scene_tabs_context_menu->set_item_disabled(-1, true); \171}172173scene_tabs_context_menu->clear();174scene_tabs_context_menu->reset_size();175176int tab_id = scene_tabs->get_hovered_tab();177bool no_root_node = !EditorNode::get_editor_data().get_edited_scene_root(tab_id);178179scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/new_scene"), EditorNode::SCENE_NEW_SCENE);180if (tab_id >= 0) {181scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene"), EditorNode::SCENE_SAVE_SCENE);182DISABLE_LAST_OPTION_IF(no_root_node);183scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene_as"), EditorNode::SCENE_SAVE_AS_SCENE);184DISABLE_LAST_OPTION_IF(no_root_node);185}186187bool can_save_all_scenes = false;188for (int i = 0; i < EditorNode::get_editor_data().get_edited_scene_count(); i++) {189if (!EditorNode::get_editor_data().get_scene_path(i).is_empty() && EditorNode::get_editor_data().get_edited_scene_root(i)) {190can_save_all_scenes = true;191break;192}193}194scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_all_scenes"), EditorNode::SCENE_SAVE_ALL_SCENES);195DISABLE_LAST_OPTION_IF(!can_save_all_scenes);196197if (tab_id >= 0) {198const String scene_path = EditorNode::get_editor_data().get_scene_path(tab_id);199const String main_scene_path = GLOBAL_GET("application/run/main_scene");200201scene_tabs_context_menu->add_separator();202scene_tabs_context_menu->add_item(TTR("Show in FileSystem"), SCENE_SHOW_IN_FILESYSTEM);203DISABLE_LAST_OPTION_IF(!ResourceLoader::exists(scene_path));204scene_tabs_context_menu->add_item(TTR("Play This Scene"), SCENE_RUN);205DISABLE_LAST_OPTION_IF(no_root_node);206scene_tabs_context_menu->add_item(TTR("Set as Main Scene"), EditorNode::SCENE_TAB_SET_AS_MAIN_SCENE);207DISABLE_LAST_OPTION_IF(no_root_node || (!main_scene_path.is_empty() && ResourceUID::ensure_path(main_scene_path) == scene_path));208209scene_tabs_context_menu->add_separator();210scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/close_scene"), EditorNode::SCENE_CLOSE);211scene_tabs_context_menu->set_item_text(-1, TTR("Close Tab"));212scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/reopen_closed_scene"), EditorNode::SCENE_OPEN_PREV);213scene_tabs_context_menu->set_item_text(-1, TTR("Undo Close Tab"));214DISABLE_LAST_OPTION_IF(!EditorNode::get_singleton()->has_previous_closed_scenes());215scene_tabs_context_menu->add_item(TTR("Close Other Tabs"), SCENE_CLOSE_OTHERS);216DISABLE_LAST_OPTION_IF(EditorNode::get_editor_data().get_edited_scene_count() <= 1);217scene_tabs_context_menu->add_item(TTR("Close Tabs to the Right"), SCENE_CLOSE_RIGHT);218DISABLE_LAST_OPTION_IF(EditorNode::get_editor_data().get_edited_scene_count() == tab_id + 1);219scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/close_all_scenes"), EditorNode::SCENE_CLOSE_ALL);220scene_tabs_context_menu->set_item_text(-1, TTRC("Close All Tabs"));221222const PackedStringArray paths = { EditorNode::get_editor_data().get_scene_path(tab_id) };223EditorContextMenuPluginManager::get_singleton()->add_options_from_plugins(scene_tabs_context_menu, EditorContextMenuPlugin::CONTEXT_SLOT_SCENE_TABS, paths);224} else {225scene_tabs_context_menu->add_separator();226scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/reopen_closed_scene"), EditorNode::SCENE_OPEN_PREV);227scene_tabs_context_menu->set_item_text(-1, TTRC("Undo Close Tab"));228DISABLE_LAST_OPTION_IF(!EditorNode::get_singleton()->has_previous_closed_scenes());229scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/close_all_scenes"), EditorNode::SCENE_CLOSE_ALL);230scene_tabs_context_menu->set_item_text(-1, TTRC("Close All Tabs"));231232EditorContextMenuPluginManager::get_singleton()->add_options_from_plugins(scene_tabs_context_menu, EditorContextMenuPlugin::CONTEXT_SLOT_SCENE_TABS, {});233}234#undef DISABLE_LAST_OPTION_IF235236last_hovered_tab = tab_id;237}238239void EditorSceneTabs::_custom_menu_option(int p_option) {240if (p_option >= EditorContextMenuPlugin::BASE_ID) {241EditorContextMenuPluginManager::get_singleton()->activate_custom_option(EditorContextMenuPlugin::CONTEXT_SLOT_SCENE_TABS, p_option, last_hovered_tab >= 0 ? EditorNode::get_editor_data().get_scene_path(last_hovered_tab) : String());242}243}244245void EditorSceneTabs::_update_scene_list() {246PopupMenu *popup = scene_list->get_popup();247popup->clear();248249for (int i = 0; i < scene_tabs->get_tab_count(); i++) {250popup->add_item(scene_tabs->get_tab_title(i), i);251popup->set_item_icon(i, scene_tabs->get_tab_icon(i));252}253}254255void EditorSceneTabs::update_scene_tabs() {256static bool menu_initialized = false;257tab_preview_panel->hide();258259if (menu_initialized && scene_tabs->get_tab_count() == EditorNode::get_editor_data().get_edited_scene_count()) {260_update_tab_titles();261return;262}263menu_initialized = true;264265if (NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU)) {266RID dock_rid = NativeMenu::get_singleton()->get_system_menu(NativeMenu::DOCK_MENU_ID);267NativeMenu::get_singleton()->clear(dock_rid);268}269270scene_tabs->set_block_signals(true);271scene_tabs->set_tab_count(EditorNode::get_editor_data().get_edited_scene_count());272scene_tabs->set_block_signals(false);273274if (NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU)) {275RID dock_rid = NativeMenu::get_singleton()->get_system_menu(NativeMenu::DOCK_MENU_ID);276for (int i = 0; i < EditorNode::get_editor_data().get_edited_scene_count(); i++) {277int global_menu_index = NativeMenu::get_singleton()->add_item(dock_rid, EditorNode::get_editor_data().get_scene_title(i), callable_mp(this, &EditorSceneTabs::_global_menu_scene), Callable(), i);278scene_tabs->set_tab_metadata(i, global_menu_index);279}280NativeMenu::get_singleton()->add_separator(dock_rid);281NativeMenu::get_singleton()->add_item(dock_rid, TTR("New Window"), callable_mp(this, &EditorSceneTabs::_global_menu_new_window));282}283284_update_tab_titles();285}286287void EditorSceneTabs::_update_tab_titles() {288bool show_rb = EDITOR_GET("interface/scene_tabs/show_script_button");289290// Get all scene names, which may be ambiguous.291Vector<String> disambiguated_scene_names;292Vector<String> full_path_names;293for (int i = 0; i < EditorNode::get_editor_data().get_edited_scene_count(); i++) {294disambiguated_scene_names.append(EditorNode::get_editor_data().get_scene_title(i));295full_path_names.append(EditorNode::get_editor_data().get_scene_path(i));296}297EditorNode::disambiguate_filenames(full_path_names, disambiguated_scene_names);298299Ref<Texture2D> script_icon = get_editor_theme_icon(SNAME("Script"));300for (int i = 0; i < EditorNode::get_editor_data().get_edited_scene_count(); i++) {301Node *type_node = EditorNode::get_editor_data().get_edited_scene_root(i);302Ref<Texture2D> icon;303if (type_node) {304icon = EditorNode::get_singleton()->get_object_icon(type_node);305}306scene_tabs->set_tab_icon(i, icon);307308bool unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(EditorNode::get_editor_data().get_scene_history_id(i));309scene_tabs->set_tab_title(i, disambiguated_scene_names[i] + (unsaved ? "(*)" : ""));310311if (NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU)) {312RID dock_rid = NativeMenu::get_singleton()->get_system_menu(NativeMenu::DOCK_MENU_ID);313int global_menu_index = scene_tabs->get_tab_metadata(i);314NativeMenu::get_singleton()->set_item_text(dock_rid, global_menu_index, EditorNode::get_editor_data().get_scene_title(i) + (unsaved ? "(*)" : ""));315NativeMenu::get_singleton()->set_item_tag(dock_rid, global_menu_index, i);316}317318if (show_rb && EditorNode::get_editor_data().get_scene_root_script(i).is_valid()) {319scene_tabs->set_tab_button_icon(i, script_icon);320} else {321scene_tabs->set_tab_button_icon(i, nullptr);322}323}324325int current_tab = EditorNode::get_editor_data().get_edited_scene();326if (scene_tabs->get_tab_count() > 0 && scene_tabs->get_current_tab() != current_tab) {327scene_tabs->set_block_signals(true);328scene_tabs->set_current_tab(current_tab);329scene_tabs->set_block_signals(false);330}331332_scene_tabs_resized();333}334335void EditorSceneTabs::_scene_tabs_resized() {336const Size2 add_button_size = Size2(scene_tab_add->get_size().x, scene_tabs->get_size().y);337if (scene_tabs->get_offset_buttons_visible()) {338// Move the add button to a fixed position.339if (scene_tab_add->get_parent() == scene_tabs) {340scene_tabs->remove_child(scene_tab_add);341scene_tab_add_ph->add_child(scene_tab_add);342scene_tab_add->set_rect(Rect2(Point2(), add_button_size));343}344} else {345// Move the add button to be after the last tab.346if (scene_tab_add->get_parent() == scene_tab_add_ph) {347scene_tab_add_ph->remove_child(scene_tab_add);348scene_tabs->add_child(scene_tab_add);349}350351if (scene_tabs->get_tab_count() == 0) {352scene_tab_add->set_rect(Rect2(Point2(), add_button_size));353return;354}355356Rect2 last_tab = scene_tabs->get_tab_rect(scene_tabs->get_tab_count() - 1);357int hsep = scene_tabs->get_theme_constant(SNAME("h_separation"));358if (scene_tabs->is_layout_rtl()) {359scene_tab_add->set_rect(Rect2(Point2(last_tab.position.x - add_button_size.x - hsep, last_tab.position.y), add_button_size));360} else {361scene_tab_add->set_rect(Rect2(Point2(last_tab.position.x + last_tab.size.width + hsep, last_tab.position.y), add_button_size));362}363}364}365366void EditorSceneTabs::_tab_preview_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, int p_tab) {367if (p_preview.is_valid()) {368tab_preview->set_texture(p_preview);369370Rect2 rect = scene_tabs->get_tab_rect(p_tab);371rect.position += scene_tabs->get_global_position();372tab_preview_panel->set_global_position(rect.position + Vector2(0, rect.size.height));373tab_preview_panel->show();374}375}376377void EditorSceneTabs::_global_menu_scene(const Variant &p_tag) {378int idx = (int)p_tag;379scene_tabs->set_current_tab(idx);380}381382void EditorSceneTabs::_global_menu_new_window(const Variant &p_tag) {383if (OS::get_singleton()->get_main_loop()) {384List<String> args;385args.push_back("-p");386OS::get_singleton()->create_instance(args);387}388}389390void EditorSceneTabs::shortcut_input(const Ref<InputEvent> &p_event) {391ERR_FAIL_COND(p_event.is_null());392393Ref<InputEventKey> k = p_event;394if ((k.is_valid() && k->is_pressed() && !k->is_echo()) || Object::cast_to<InputEventShortcut>(*p_event)) {395if (ED_IS_SHORTCUT("editor/next_tab", p_event)) {396int next_tab = EditorNode::get_editor_data().get_edited_scene() + 1;397next_tab %= EditorNode::get_editor_data().get_edited_scene_count();398_scene_tab_changed(next_tab);399}400if (ED_IS_SHORTCUT("editor/prev_tab", p_event)) {401int next_tab = EditorNode::get_editor_data().get_edited_scene() - 1;402next_tab = next_tab >= 0 ? next_tab : EditorNode::get_editor_data().get_edited_scene_count() - 1;403_scene_tab_changed(next_tab);404}405}406}407408void EditorSceneTabs::add_extra_button(Button *p_button) {409tabbar_container->add_child(p_button);410}411412void EditorSceneTabs::set_current_tab(int p_tab) {413scene_tabs->set_current_tab(p_tab);414}415416int EditorSceneTabs::get_current_tab() const {417return scene_tabs->get_current_tab();418}419420void EditorSceneTabs::_bind_methods() {421ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab_index")));422ADD_SIGNAL(MethodInfo("tab_closed", PropertyInfo(Variant::INT, "tab_index")));423}424425EditorSceneTabs::EditorSceneTabs() {426singleton = this;427428set_process_shortcut_input(true);429set_process_unhandled_key_input(true);430431tabbar_panel = memnew(PanelContainer);432add_child(tabbar_panel);433tabbar_container = memnew(HBoxContainer);434tabbar_panel->add_child(tabbar_container);435436scene_tabs = memnew(TabBar);437scene_tabs->set_select_with_rmb(true);438scene_tabs->add_tab("unsaved");439scene_tabs->set_tab_close_display_policy((TabBar::CloseButtonDisplayPolicy)EDITOR_GET("interface/scene_tabs/display_close_button").operator int());440scene_tabs->set_max_tab_width(int(EDITOR_GET("interface/scene_tabs/maximum_width")) * EDSCALE);441scene_tabs->set_drag_to_rearrange_enabled(true);442scene_tabs->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);443scene_tabs->set_h_size_flags(Control::SIZE_EXPAND_FILL);444tabbar_container->add_child(scene_tabs);445446scene_tabs->connect("tab_changed", callable_mp(this, &EditorSceneTabs::_scene_tab_changed));447scene_tabs->connect("tab_button_pressed", callable_mp(this, &EditorSceneTabs::_scene_tab_script_edited));448scene_tabs->connect("tab_close_pressed", callable_mp(this, &EditorSceneTabs::_scene_tab_closed));449scene_tabs->connect("tab_hovered", callable_mp(this, &EditorSceneTabs::_scene_tab_hovered));450scene_tabs->connect(SceneStringName(mouse_exited), callable_mp(this, &EditorSceneTabs::_scene_tab_exit));451scene_tabs->connect(SceneStringName(gui_input), callable_mp(this, &EditorSceneTabs::_scene_tab_input));452scene_tabs->connect("active_tab_rearranged", callable_mp(this, &EditorSceneTabs::_reposition_active_tab));453scene_tabs->connect(SceneStringName(resized), callable_mp(this, &EditorSceneTabs::_scene_tabs_resized), CONNECT_DEFERRED);454455scene_tabs_context_menu = memnew(PopupMenu);456tabbar_container->add_child(scene_tabs_context_menu);457scene_tabs_context_menu->connect(SceneStringName(id_pressed), callable_mp(EditorNode::get_singleton(), &EditorNode::trigger_menu_option).bind(false));458scene_tabs_context_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorSceneTabs::_custom_menu_option));459460scene_tab_add = memnew(Button);461scene_tab_add->set_flat(true);462scene_tab_add->set_tooltip_text(TTR("Add a new scene."));463scene_tabs->add_child(scene_tab_add);464scene_tab_add->connect(SceneStringName(pressed), callable_mp(EditorNode::get_singleton(), &EditorNode::trigger_menu_option).bind(EditorNode::SCENE_NEW_SCENE, false));465466scene_tab_add_ph = memnew(Control);467scene_tab_add_ph->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);468scene_tab_add_ph->set_custom_minimum_size(scene_tab_add->get_minimum_size());469tabbar_container->add_child(scene_tab_add_ph);470471scene_list = memnew(MenuButton);472scene_list->set_flat(false);473scene_list->set_theme_type_variation("FlatMenuButton");474scene_list->set_accessibility_name(TTRC("Show Opened Scenes List"));475scene_list->set_shortcut(ED_SHORTCUT("editor/show_opened_scenes_list", TTRC("Show Opened Scenes List"), KeyModifierMask::ALT | Key::T));476scene_list->get_popup()->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);477scene_list->get_popup()->connect("about_to_popup", callable_mp(this, &EditorSceneTabs::_update_scene_list));478scene_list->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &EditorSceneTabs::_scene_tab_changed));479tabbar_container->add_child(scene_list);480481// On-hover tab preview.482483Control *tab_preview_anchor = memnew(Control);484tab_preview_anchor->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);485add_child(tab_preview_anchor);486487tab_preview_panel = memnew(Panel);488tab_preview_panel->set_size(Size2(100, 100) * EDSCALE);489tab_preview_panel->hide();490tab_preview_panel->set_self_modulate(Color(1, 1, 1, 0.7));491tab_preview_anchor->add_child(tab_preview_panel);492493tab_preview = memnew(TextureRect);494tab_preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);495tab_preview->set_size(Size2(96, 96) * EDSCALE);496tab_preview->set_position(Point2(2, 2) * EDSCALE);497tab_preview_panel->add_child(tab_preview);498}499500501