Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/editor/scene/editor_scene_tabs.cpp
9903 views
1
/**************************************************************************/
2
/* editor_scene_tabs.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 "editor_scene_tabs.h"
32
33
#include "editor/docks/inspector_dock.h"
34
#include "editor/editor_main_screen.h"
35
#include "editor/editor_node.h"
36
#include "editor/editor_string_names.h"
37
#include "editor/editor_undo_redo_manager.h"
38
#include "editor/inspector/editor_context_menu_plugin.h"
39
#include "editor/inspector/editor_resource_preview.h"
40
#include "editor/run/editor_run_bar.h"
41
#include "editor/settings/editor_settings.h"
42
#include "editor/themes/editor_scale.h"
43
#include "scene/gui/box_container.h"
44
#include "scene/gui/button.h"
45
#include "scene/gui/panel.h"
46
#include "scene/gui/panel_container.h"
47
#include "scene/gui/popup_menu.h"
48
#include "scene/gui/tab_bar.h"
49
#include "scene/gui/texture_rect.h"
50
51
void EditorSceneTabs::_notification(int p_what) {
52
switch (p_what) {
53
case NOTIFICATION_THEME_CHANGED: {
54
tabbar_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("tabbar_background"), SNAME("TabContainer")));
55
scene_tabs->add_theme_constant_override("icon_max_width", get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor)));
56
57
scene_tab_add->set_button_icon(get_editor_theme_icon(SNAME("Add")));
58
scene_tab_add->add_theme_color_override("icon_normal_color", Color(0.6f, 0.6f, 0.6f, 0.8f));
59
60
scene_tab_add_ph->set_custom_minimum_size(scene_tab_add->get_minimum_size());
61
} break;
62
63
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
64
if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/scene_tabs")) {
65
scene_tabs->set_tab_close_display_policy((TabBar::CloseButtonDisplayPolicy)EDITOR_GET("interface/scene_tabs/display_close_button").operator int());
66
scene_tabs->set_max_tab_width(int(EDITOR_GET("interface/scene_tabs/maximum_width")) * EDSCALE);
67
_scene_tabs_resized();
68
}
69
} break;
70
71
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
72
case NOTIFICATION_TRANSLATION_CHANGED: {
73
_scene_tabs_resized();
74
} break;
75
}
76
}
77
78
void EditorSceneTabs::_scene_tab_changed(int p_tab) {
79
tab_preview_panel->hide();
80
81
emit_signal("tab_changed", p_tab);
82
}
83
84
void EditorSceneTabs::_scene_tab_script_edited(int p_tab) {
85
Ref<Script> scr = EditorNode::get_editor_data().get_scene_root_script(p_tab);
86
if (scr.is_valid()) {
87
InspectorDock::get_singleton()->edit_resource(scr);
88
}
89
}
90
91
void EditorSceneTabs::_scene_tab_closed(int p_tab) {
92
emit_signal("tab_closed", p_tab);
93
}
94
95
void EditorSceneTabs::_scene_tab_hovered(int p_tab) {
96
if (!bool(EDITOR_GET("interface/scene_tabs/show_thumbnail_on_hover"))) {
97
return;
98
}
99
100
// Currently the tab previews are displayed under the running game process when embed.
101
// Right now, the easiest technique to fix that is to prevent displaying the tab preview
102
// when the user is in the Game View.
103
if (EditorNode::get_singleton()->get_editor_main_screen()->get_selected_index() == EditorMainScreen::EDITOR_GAME && EditorRunBar::get_singleton()->is_playing()) {
104
return;
105
}
106
107
int current_tab = scene_tabs->get_current_tab();
108
109
if (p_tab == current_tab || p_tab < 0) {
110
tab_preview_panel->hide();
111
} else {
112
String path = EditorNode::get_editor_data().get_scene_path(p_tab);
113
if (!path.is_empty()) {
114
EditorResourcePreview::get_singleton()->queue_resource_preview(path, this, "_tab_preview_done", p_tab);
115
}
116
}
117
}
118
119
void EditorSceneTabs::_scene_tab_exit() {
120
tab_preview_panel->hide();
121
}
122
123
void EditorSceneTabs::_scene_tab_input(const Ref<InputEvent> &p_input) {
124
Ref<InputEventMouseButton> mb = p_input;
125
126
if (mb.is_valid()) {
127
if (mb->get_button_index() == MouseButton::LEFT && mb->is_double_click()) {
128
int tab_buttons = 0;
129
if (scene_tabs->get_offset_buttons_visible()) {
130
tab_buttons = get_theme_icon(SNAME("increment"), SNAME("TabBar"))->get_width() + get_theme_icon(SNAME("decrement"), SNAME("TabBar"))->get_width();
131
}
132
133
if ((is_layout_rtl() && mb->get_position().x > tab_buttons) || (!is_layout_rtl() && mb->get_position().x < scene_tabs->get_size().width - tab_buttons)) {
134
EditorNode::get_singleton()->trigger_menu_option(EditorNode::SCENE_NEW_SCENE, true);
135
}
136
}
137
if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) {
138
// Context menu.
139
_update_context_menu();
140
141
scene_tabs_context_menu->set_position(scene_tabs->get_screen_position() + mb->get_position());
142
scene_tabs_context_menu->reset_size();
143
scene_tabs_context_menu->popup();
144
}
145
}
146
}
147
148
void EditorSceneTabs::unhandled_key_input(const Ref<InputEvent> &p_event) {
149
if (!tab_preview_panel->is_visible()) {
150
return;
151
}
152
153
Ref<InputEventKey> k = p_event;
154
if (k.is_valid() && k->is_action_pressed(SNAME("ui_cancel"), false, true)) {
155
tab_preview_panel->hide();
156
}
157
}
158
159
void EditorSceneTabs::_reposition_active_tab(int p_to_index) {
160
EditorNode::get_editor_data().move_edited_scene_to_index(p_to_index);
161
update_scene_tabs();
162
}
163
164
void EditorSceneTabs::_update_context_menu() {
165
#define DISABLE_LAST_OPTION_IF(m_condition) \
166
if (m_condition) { \
167
scene_tabs_context_menu->set_item_disabled(-1, true); \
168
}
169
170
scene_tabs_context_menu->clear();
171
scene_tabs_context_menu->reset_size();
172
173
int tab_id = scene_tabs->get_hovered_tab();
174
bool no_root_node = !EditorNode::get_editor_data().get_edited_scene_root(tab_id);
175
176
scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/new_scene"), EditorNode::SCENE_NEW_SCENE);
177
if (tab_id >= 0) {
178
scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene"), EditorNode::SCENE_SAVE_SCENE);
179
DISABLE_LAST_OPTION_IF(no_root_node);
180
scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene_as"), EditorNode::SCENE_SAVE_AS_SCENE);
181
DISABLE_LAST_OPTION_IF(no_root_node);
182
}
183
184
bool can_save_all_scenes = false;
185
for (int i = 0; i < EditorNode::get_editor_data().get_edited_scene_count(); i++) {
186
if (!EditorNode::get_editor_data().get_scene_path(i).is_empty() && EditorNode::get_editor_data().get_edited_scene_root(i)) {
187
can_save_all_scenes = true;
188
break;
189
}
190
}
191
scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_all_scenes"), EditorNode::SCENE_SAVE_ALL_SCENES);
192
DISABLE_LAST_OPTION_IF(!can_save_all_scenes);
193
194
if (tab_id >= 0) {
195
scene_tabs_context_menu->add_separator();
196
scene_tabs_context_menu->add_item(TTR("Show in FileSystem"), SCENE_SHOW_IN_FILESYSTEM);
197
DISABLE_LAST_OPTION_IF(!ResourceLoader::exists(EditorNode::get_editor_data().get_scene_path(tab_id)));
198
scene_tabs_context_menu->add_item(TTR("Play This Scene"), SCENE_RUN);
199
DISABLE_LAST_OPTION_IF(no_root_node);
200
201
scene_tabs_context_menu->add_separator();
202
scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/close_scene"), EditorNode::SCENE_CLOSE);
203
scene_tabs_context_menu->set_item_text(-1, TTR("Close Tab"));
204
scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/reopen_closed_scene"), EditorNode::SCENE_OPEN_PREV);
205
scene_tabs_context_menu->set_item_text(-1, TTR("Undo Close Tab"));
206
DISABLE_LAST_OPTION_IF(!EditorNode::get_singleton()->has_previous_closed_scenes());
207
scene_tabs_context_menu->add_item(TTR("Close Other Tabs"), SCENE_CLOSE_OTHERS);
208
DISABLE_LAST_OPTION_IF(EditorNode::get_editor_data().get_edited_scene_count() <= 1);
209
scene_tabs_context_menu->add_item(TTR("Close Tabs to the Right"), SCENE_CLOSE_RIGHT);
210
DISABLE_LAST_OPTION_IF(EditorNode::get_editor_data().get_edited_scene_count() == tab_id + 1);
211
scene_tabs_context_menu->add_item(TTR("Close All Tabs"), SCENE_CLOSE_ALL);
212
213
const PackedStringArray paths = { EditorNode::get_editor_data().get_scene_path(tab_id) };
214
EditorContextMenuPluginManager::get_singleton()->add_options_from_plugins(scene_tabs_context_menu, EditorContextMenuPlugin::CONTEXT_SLOT_SCENE_TABS, paths);
215
} else {
216
EditorContextMenuPluginManager::get_singleton()->add_options_from_plugins(scene_tabs_context_menu, EditorContextMenuPlugin::CONTEXT_SLOT_SCENE_TABS, {});
217
}
218
#undef DISABLE_LAST_OPTION_IF
219
220
last_hovered_tab = tab_id;
221
}
222
223
void EditorSceneTabs::_custom_menu_option(int p_option) {
224
if (p_option >= EditorContextMenuPlugin::BASE_ID) {
225
EditorContextMenuPluginManager::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());
226
}
227
}
228
229
void EditorSceneTabs::update_scene_tabs() {
230
static bool menu_initialized = false;
231
tab_preview_panel->hide();
232
233
if (menu_initialized && scene_tabs->get_tab_count() == EditorNode::get_editor_data().get_edited_scene_count()) {
234
_update_tab_titles();
235
return;
236
}
237
menu_initialized = true;
238
239
if (NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU)) {
240
RID dock_rid = NativeMenu::get_singleton()->get_system_menu(NativeMenu::DOCK_MENU_ID);
241
NativeMenu::get_singleton()->clear(dock_rid);
242
}
243
244
scene_tabs->set_block_signals(true);
245
scene_tabs->set_tab_count(EditorNode::get_editor_data().get_edited_scene_count());
246
scene_tabs->set_block_signals(false);
247
248
if (NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU)) {
249
RID dock_rid = NativeMenu::get_singleton()->get_system_menu(NativeMenu::DOCK_MENU_ID);
250
for (int i = 0; i < EditorNode::get_editor_data().get_edited_scene_count(); i++) {
251
int 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);
252
scene_tabs->set_tab_metadata(i, global_menu_index);
253
}
254
NativeMenu::get_singleton()->add_separator(dock_rid);
255
NativeMenu::get_singleton()->add_item(dock_rid, TTR("New Window"), callable_mp(this, &EditorSceneTabs::_global_menu_new_window));
256
}
257
258
_update_tab_titles();
259
}
260
261
void EditorSceneTabs::_update_tab_titles() {
262
bool show_rb = EDITOR_GET("interface/scene_tabs/show_script_button");
263
264
// Get all scene names, which may be ambiguous.
265
Vector<String> disambiguated_scene_names;
266
Vector<String> full_path_names;
267
for (int i = 0; i < EditorNode::get_editor_data().get_edited_scene_count(); i++) {
268
disambiguated_scene_names.append(EditorNode::get_editor_data().get_scene_title(i));
269
full_path_names.append(EditorNode::get_editor_data().get_scene_path(i));
270
}
271
EditorNode::disambiguate_filenames(full_path_names, disambiguated_scene_names);
272
273
Ref<Texture2D> script_icon = get_editor_theme_icon(SNAME("Script"));
274
for (int i = 0; i < EditorNode::get_editor_data().get_edited_scene_count(); i++) {
275
Node *type_node = EditorNode::get_editor_data().get_edited_scene_root(i);
276
Ref<Texture2D> icon;
277
if (type_node) {
278
icon = EditorNode::get_singleton()->get_object_icon(type_node, "Node");
279
}
280
scene_tabs->set_tab_icon(i, icon);
281
282
bool unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(EditorNode::get_editor_data().get_scene_history_id(i));
283
scene_tabs->set_tab_title(i, disambiguated_scene_names[i] + (unsaved ? "(*)" : ""));
284
285
if (NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU)) {
286
RID dock_rid = NativeMenu::get_singleton()->get_system_menu(NativeMenu::DOCK_MENU_ID);
287
int global_menu_index = scene_tabs->get_tab_metadata(i);
288
NativeMenu::get_singleton()->set_item_text(dock_rid, global_menu_index, EditorNode::get_editor_data().get_scene_title(i) + (unsaved ? "(*)" : ""));
289
NativeMenu::get_singleton()->set_item_tag(dock_rid, global_menu_index, i);
290
}
291
292
if (show_rb && EditorNode::get_editor_data().get_scene_root_script(i).is_valid()) {
293
scene_tabs->set_tab_button_icon(i, script_icon);
294
} else {
295
scene_tabs->set_tab_button_icon(i, nullptr);
296
}
297
}
298
299
int current_tab = EditorNode::get_editor_data().get_edited_scene();
300
if (scene_tabs->get_tab_count() > 0 && scene_tabs->get_current_tab() != current_tab) {
301
scene_tabs->set_block_signals(true);
302
scene_tabs->set_current_tab(current_tab);
303
scene_tabs->set_block_signals(false);
304
}
305
306
_scene_tabs_resized();
307
}
308
309
void EditorSceneTabs::_scene_tabs_resized() {
310
const Size2 add_button_size = Size2(scene_tab_add->get_size().x, scene_tabs->get_size().y);
311
if (scene_tabs->get_offset_buttons_visible()) {
312
// Move the add button to a fixed position.
313
if (scene_tab_add->get_parent() == scene_tabs) {
314
scene_tabs->remove_child(scene_tab_add);
315
scene_tab_add_ph->add_child(scene_tab_add);
316
scene_tab_add->set_rect(Rect2(Point2(), add_button_size));
317
}
318
} else {
319
// Move the add button to be after the last tab.
320
if (scene_tab_add->get_parent() == scene_tab_add_ph) {
321
scene_tab_add_ph->remove_child(scene_tab_add);
322
scene_tabs->add_child(scene_tab_add);
323
}
324
325
if (scene_tabs->get_tab_count() == 0) {
326
scene_tab_add->set_rect(Rect2(Point2(), add_button_size));
327
return;
328
}
329
330
Rect2 last_tab = scene_tabs->get_tab_rect(scene_tabs->get_tab_count() - 1);
331
int hsep = scene_tabs->get_theme_constant(SNAME("h_separation"));
332
if (scene_tabs->is_layout_rtl()) {
333
scene_tab_add->set_rect(Rect2(Point2(last_tab.position.x - add_button_size.x - hsep, last_tab.position.y), add_button_size));
334
} else {
335
scene_tab_add->set_rect(Rect2(Point2(last_tab.position.x + last_tab.size.width + hsep, last_tab.position.y), add_button_size));
336
}
337
}
338
}
339
340
void EditorSceneTabs::_tab_preview_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, const Variant &p_udata) {
341
int p_tab = p_udata;
342
if (p_preview.is_valid()) {
343
tab_preview->set_texture(p_preview);
344
345
Rect2 rect = scene_tabs->get_tab_rect(p_tab);
346
rect.position += scene_tabs->get_global_position();
347
tab_preview_panel->set_global_position(rect.position + Vector2(0, rect.size.height));
348
tab_preview_panel->show();
349
}
350
}
351
352
void EditorSceneTabs::_global_menu_scene(const Variant &p_tag) {
353
int idx = (int)p_tag;
354
scene_tabs->set_current_tab(idx);
355
}
356
357
void EditorSceneTabs::_global_menu_new_window(const Variant &p_tag) {
358
if (OS::get_singleton()->get_main_loop()) {
359
List<String> args;
360
args.push_back("-p");
361
OS::get_singleton()->create_instance(args);
362
}
363
}
364
365
void EditorSceneTabs::shortcut_input(const Ref<InputEvent> &p_event) {
366
ERR_FAIL_COND(p_event.is_null());
367
368
Ref<InputEventKey> k = p_event;
369
if ((k.is_valid() && k->is_pressed() && !k->is_echo()) || Object::cast_to<InputEventShortcut>(*p_event)) {
370
if (ED_IS_SHORTCUT("editor/next_tab", p_event)) {
371
int next_tab = EditorNode::get_editor_data().get_edited_scene() + 1;
372
next_tab %= EditorNode::get_editor_data().get_edited_scene_count();
373
_scene_tab_changed(next_tab);
374
}
375
if (ED_IS_SHORTCUT("editor/prev_tab", p_event)) {
376
int next_tab = EditorNode::get_editor_data().get_edited_scene() - 1;
377
next_tab = next_tab >= 0 ? next_tab : EditorNode::get_editor_data().get_edited_scene_count() - 1;
378
_scene_tab_changed(next_tab);
379
}
380
}
381
}
382
383
void EditorSceneTabs::add_extra_button(Button *p_button) {
384
tabbar_container->add_child(p_button);
385
}
386
387
void EditorSceneTabs::set_current_tab(int p_tab) {
388
scene_tabs->set_current_tab(p_tab);
389
}
390
391
int EditorSceneTabs::get_current_tab() const {
392
return scene_tabs->get_current_tab();
393
}
394
395
void EditorSceneTabs::_bind_methods() {
396
ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab_index")));
397
ADD_SIGNAL(MethodInfo("tab_closed", PropertyInfo(Variant::INT, "tab_index")));
398
399
ClassDB::bind_method("_tab_preview_done", &EditorSceneTabs::_tab_preview_done);
400
}
401
402
EditorSceneTabs::EditorSceneTabs() {
403
singleton = this;
404
405
set_process_shortcut_input(true);
406
set_process_unhandled_key_input(true);
407
408
tabbar_panel = memnew(PanelContainer);
409
add_child(tabbar_panel);
410
tabbar_container = memnew(HBoxContainer);
411
tabbar_panel->add_child(tabbar_container);
412
413
scene_tabs = memnew(TabBar);
414
scene_tabs->set_select_with_rmb(true);
415
scene_tabs->add_tab("unsaved");
416
scene_tabs->set_tab_close_display_policy((TabBar::CloseButtonDisplayPolicy)EDITOR_GET("interface/scene_tabs/display_close_button").operator int());
417
scene_tabs->set_max_tab_width(int(EDITOR_GET("interface/scene_tabs/maximum_width")) * EDSCALE);
418
scene_tabs->set_drag_to_rearrange_enabled(true);
419
scene_tabs->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
420
scene_tabs->set_h_size_flags(Control::SIZE_EXPAND_FILL);
421
tabbar_container->add_child(scene_tabs);
422
423
scene_tabs->connect("tab_changed", callable_mp(this, &EditorSceneTabs::_scene_tab_changed));
424
scene_tabs->connect("tab_button_pressed", callable_mp(this, &EditorSceneTabs::_scene_tab_script_edited));
425
scene_tabs->connect("tab_close_pressed", callable_mp(this, &EditorSceneTabs::_scene_tab_closed));
426
scene_tabs->connect("tab_hovered", callable_mp(this, &EditorSceneTabs::_scene_tab_hovered));
427
scene_tabs->connect(SceneStringName(mouse_exited), callable_mp(this, &EditorSceneTabs::_scene_tab_exit));
428
scene_tabs->connect(SceneStringName(gui_input), callable_mp(this, &EditorSceneTabs::_scene_tab_input));
429
scene_tabs->connect("active_tab_rearranged", callable_mp(this, &EditorSceneTabs::_reposition_active_tab));
430
scene_tabs->connect(SceneStringName(resized), callable_mp(this, &EditorSceneTabs::_scene_tabs_resized), CONNECT_DEFERRED);
431
432
scene_tabs_context_menu = memnew(PopupMenu);
433
tabbar_container->add_child(scene_tabs_context_menu);
434
scene_tabs_context_menu->connect(SceneStringName(id_pressed), callable_mp(EditorNode::get_singleton(), &EditorNode::trigger_menu_option).bind(false));
435
scene_tabs_context_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorSceneTabs::_custom_menu_option));
436
437
scene_tab_add = memnew(Button);
438
scene_tab_add->set_flat(true);
439
scene_tab_add->set_tooltip_text(TTR("Add a new scene."));
440
scene_tabs->add_child(scene_tab_add);
441
scene_tab_add->connect(SceneStringName(pressed), callable_mp(EditorNode::get_singleton(), &EditorNode::trigger_menu_option).bind(EditorNode::SCENE_NEW_SCENE, false));
442
443
scene_tab_add_ph = memnew(Control);
444
scene_tab_add_ph->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
445
scene_tab_add_ph->set_custom_minimum_size(scene_tab_add->get_minimum_size());
446
tabbar_container->add_child(scene_tab_add_ph);
447
448
// On-hover tab preview.
449
450
Control *tab_preview_anchor = memnew(Control);
451
tab_preview_anchor->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
452
add_child(tab_preview_anchor);
453
454
tab_preview_panel = memnew(Panel);
455
tab_preview_panel->set_size(Size2(100, 100) * EDSCALE);
456
tab_preview_panel->hide();
457
tab_preview_panel->set_self_modulate(Color(1, 1, 1, 0.7));
458
tab_preview_anchor->add_child(tab_preview_panel);
459
460
tab_preview = memnew(TextureRect);
461
tab_preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
462
tab_preview->set_size(Size2(96, 96) * EDSCALE);
463
tab_preview->set_position(Point2(2, 2) * EDSCALE);
464
tab_preview_panel->add_child(tab_preview);
465
}
466
467