Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/editor/editor_main_screen.cpp
20837 views
1
/**************************************************************************/
2
/* editor_main_screen.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_main_screen.h"
32
33
#include "core/io/config_file.h"
34
#include "editor/editor_node.h"
35
#include "editor/editor_string_names.h"
36
#include "editor/plugins/editor_plugin.h"
37
#include "editor/settings/editor_settings.h"
38
#include "scene/gui/box_container.h"
39
#include "scene/gui/button.h"
40
41
void EditorMainScreen::_notification(int p_what) {
42
switch (p_what) {
43
case NOTIFICATION_READY: {
44
set_accessibility_region(true);
45
if (EDITOR_3D < buttons.size() && buttons[EDITOR_3D]->is_visible()) {
46
// If the 3D editor is enabled, use this as the default.
47
select(EDITOR_3D);
48
return;
49
}
50
51
// Switch to the first main screen plugin that is enabled. Usually this is
52
// 2D, but may be subsequent ones if 2D is disabled in the feature profile.
53
for (int i = 0; i < buttons.size(); i++) {
54
Button *editor_button = buttons[i];
55
if (editor_button->is_visible()) {
56
select(i);
57
return;
58
}
59
}
60
61
select(-1);
62
} break;
63
case NOTIFICATION_THEME_CHANGED: {
64
for (int i = 0; i < buttons.size(); i++) {
65
Button *tb = buttons[i];
66
EditorPlugin *p_editor = editor_table[i];
67
Ref<Texture2D> icon = p_editor->get_plugin_icon();
68
69
if (icon.is_valid()) {
70
tb->set_button_icon(icon);
71
} else if (has_theme_icon(p_editor->get_plugin_name(), EditorStringName(EditorIcons))) {
72
tb->set_button_icon(get_theme_icon(p_editor->get_plugin_name(), EditorStringName(EditorIcons)));
73
}
74
}
75
} break;
76
}
77
}
78
79
void EditorMainScreen::set_button_container(HBoxContainer *p_button_hb) {
80
button_hb = p_button_hb;
81
}
82
83
void EditorMainScreen::save_layout_to_config(Ref<ConfigFile> p_config_file, const String &p_section) const {
84
int selected_main_editor_idx = -1;
85
for (int i = 0; i < buttons.size(); i++) {
86
if (buttons[i]->is_pressed()) {
87
selected_main_editor_idx = i;
88
break;
89
}
90
}
91
if (selected_main_editor_idx != -1) {
92
p_config_file->set_value(p_section, "selected_main_editor_idx", selected_main_editor_idx);
93
} else {
94
p_config_file->set_value(p_section, "selected_main_editor_idx", Variant());
95
}
96
}
97
98
void EditorMainScreen::load_layout_from_config(Ref<ConfigFile> p_config_file, const String &p_section) {
99
int selected_main_editor_idx = p_config_file->get_value(p_section, "selected_main_editor_idx", -1);
100
if (selected_main_editor_idx >= 0 && selected_main_editor_idx < buttons.size()) {
101
callable_mp(this, &EditorMainScreen::select).call_deferred(selected_main_editor_idx);
102
}
103
}
104
105
void EditorMainScreen::set_button_enabled(int p_index, bool p_enabled) {
106
ERR_FAIL_INDEX(p_index, buttons.size());
107
buttons[p_index]->set_visible(p_enabled);
108
if (!p_enabled && buttons[p_index]->is_pressed()) {
109
select(EDITOR_2D);
110
}
111
}
112
113
bool EditorMainScreen::is_button_enabled(int p_index) const {
114
ERR_FAIL_INDEX_V(p_index, buttons.size(), false);
115
return buttons[p_index]->is_visible();
116
}
117
118
int EditorMainScreen::_get_current_main_editor() const {
119
for (int i = 0; i < editor_table.size(); i++) {
120
if (editor_table[i] == selected_plugin) {
121
return i;
122
}
123
}
124
125
return 0;
126
}
127
128
void EditorMainScreen::select_next() {
129
int editor = _get_current_main_editor();
130
131
do {
132
if (editor == editor_table.size() - 1) {
133
editor = 0;
134
} else {
135
editor++;
136
}
137
} while (!buttons[editor]->is_visible());
138
139
select(editor);
140
}
141
142
void EditorMainScreen::select_prev() {
143
int editor = _get_current_main_editor();
144
145
do {
146
if (editor == 0) {
147
editor = editor_table.size() - 1;
148
} else {
149
editor--;
150
}
151
} while (!buttons[editor]->is_visible());
152
153
select(editor);
154
}
155
156
void EditorMainScreen::select_by_name(const String &p_name) {
157
ERR_FAIL_COND(p_name.is_empty());
158
159
for (int i = 0; i < buttons.size(); i++) {
160
if (buttons[i]->get_text() == p_name) {
161
select(i);
162
return;
163
}
164
}
165
166
ERR_FAIL_MSG("The editor name '" + p_name + "' was not found.");
167
}
168
169
void EditorMainScreen::select(int p_index) {
170
if (EditorNode::get_singleton()->is_changing_scene()) {
171
return;
172
}
173
174
ERR_FAIL_INDEX(p_index, editor_table.size());
175
176
if (!buttons[p_index]->is_visible()) { // Button hidden, no editor.
177
return;
178
}
179
180
for (int i = 0; i < buttons.size(); i++) {
181
buttons[i]->set_pressed_no_signal(i == p_index);
182
}
183
184
EditorPlugin *new_editor = editor_table[p_index];
185
ERR_FAIL_NULL(new_editor);
186
187
if (selected_plugin == new_editor) {
188
return;
189
}
190
191
if (selected_plugin) {
192
selected_plugin->make_visible(false);
193
}
194
195
selected_plugin = new_editor;
196
selected_plugin->make_visible(true);
197
selected_plugin->selected_notify();
198
set_accessibility_name(selected_plugin->get_plugin_name());
199
200
EditorData &editor_data = EditorNode::get_editor_data();
201
int plugin_count = editor_data.get_editor_plugin_count();
202
for (int i = 0; i < plugin_count; i++) {
203
editor_data.get_editor_plugin(i)->notify_main_screen_changed(selected_plugin->get_plugin_name());
204
}
205
206
EditorNode::get_singleton()->update_distraction_free_mode();
207
}
208
209
int EditorMainScreen::get_selected_index() const {
210
for (int i = 0; i < editor_table.size(); i++) {
211
if (selected_plugin == editor_table[i]) {
212
return i;
213
}
214
}
215
return -1;
216
}
217
218
int EditorMainScreen::get_plugin_index(EditorPlugin *p_editor) const {
219
int screen = -1;
220
for (int i = 0; i < editor_table.size(); i++) {
221
if (p_editor == editor_table[i]) {
222
screen = i;
223
break;
224
}
225
}
226
return screen;
227
}
228
229
EditorPlugin *EditorMainScreen::get_selected_plugin() const {
230
return selected_plugin;
231
}
232
233
EditorPlugin *EditorMainScreen::get_plugin_by_name(const String &p_plugin_name) const {
234
ERR_FAIL_COND_V(!main_editor_plugins.has(p_plugin_name), nullptr);
235
return main_editor_plugins[p_plugin_name];
236
}
237
238
bool EditorMainScreen::can_auto_switch_screens() const {
239
if (selected_plugin == nullptr) {
240
return true;
241
}
242
// Only allow auto-switching if the selected button is to the left of the Script button.
243
for (int i = 0; i < button_hb->get_child_count(); i++) {
244
Button *button = Object::cast_to<Button>(button_hb->get_child(i));
245
if (button->get_text() == "Script") {
246
// Selected button is at or after the Script button.
247
return false;
248
}
249
if (button->get_text() == selected_plugin->get_plugin_name()) {
250
// Selected button is before the Script button.
251
return true;
252
}
253
}
254
return false;
255
}
256
257
VBoxContainer *EditorMainScreen::get_control() const {
258
return main_screen_vbox;
259
}
260
261
void EditorMainScreen::add_main_plugin(EditorPlugin *p_editor) {
262
Button *tb = memnew(Button);
263
tb->set_toggle_mode(true);
264
tb->set_theme_type_variation("MainScreenButton");
265
tb->set_name(p_editor->get_plugin_name());
266
tb->set_text(p_editor->get_plugin_name());
267
268
Ref<Shortcut> shortcut = EditorSettings::get_singleton()->get_shortcut("editor/editor_" + p_editor->get_plugin_name().to_lower());
269
if (shortcut.is_valid()) {
270
tb->set_shortcut(shortcut);
271
}
272
273
Ref<Texture2D> icon = p_editor->get_plugin_icon();
274
if (icon.is_null() && has_theme_icon(p_editor->get_plugin_name(), EditorStringName(EditorIcons))) {
275
icon = get_editor_theme_icon(p_editor->get_plugin_name());
276
}
277
if (icon.is_valid()) {
278
tb->set_button_icon(icon);
279
// Make sure the control is updated if the icon is reimported.
280
icon->connect_changed(callable_mp((Control *)tb, &Control::update_minimum_size));
281
}
282
283
tb->connect(SceneStringName(pressed), callable_mp(this, &EditorMainScreen::select).bind(buttons.size()));
284
285
buttons.push_back(tb);
286
button_hb->add_child(tb);
287
editor_table.push_back(p_editor);
288
main_editor_plugins.insert(p_editor->get_plugin_name(), p_editor);
289
}
290
291
void EditorMainScreen::remove_main_plugin(EditorPlugin *p_editor) {
292
// Remove the main editor button and update the bindings of
293
// all buttons behind it to point to the correct main window.
294
for (int i = buttons.size() - 1; i >= 0; i--) {
295
if (p_editor->get_plugin_name() == buttons[i]->get_text()) {
296
if (buttons[i]->is_pressed()) {
297
select(EDITOR_SCRIPT);
298
}
299
300
memdelete(buttons[i]);
301
buttons.remove_at(i);
302
303
break;
304
} else {
305
buttons[i]->disconnect(SceneStringName(pressed), callable_mp(this, &EditorMainScreen::select));
306
buttons[i]->connect(SceneStringName(pressed), callable_mp(this, &EditorMainScreen::select).bind(i - 1));
307
}
308
}
309
310
if (selected_plugin == p_editor) {
311
selected_plugin = nullptr;
312
}
313
314
editor_table.erase(p_editor);
315
main_editor_plugins.erase(p_editor->get_plugin_name());
316
}
317
318
EditorMainScreen::EditorMainScreen() {
319
main_screen_vbox = memnew(VBoxContainer);
320
main_screen_vbox->set_name("MainScreen");
321
main_screen_vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL);
322
main_screen_vbox->add_theme_constant_override("separation", 0);
323
add_child(main_screen_vbox);
324
}
325
326