1 /*************************************************************************/
2 /*  editor_node.cpp                                                      */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
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_node.h"
32 
33 #include "core/bind/core_bind.h"
34 #include "core/class_db.h"
35 #include "core/io/config_file.h"
36 #include "core/io/image_loader.h"
37 #include "core/io/resource_loader.h"
38 #include "core/io/resource_saver.h"
39 #include "core/io/stream_peer_ssl.h"
40 #include "core/message_queue.h"
41 #include "core/os/file_access.h"
42 #include "core/os/input.h"
43 #include "core/os/keyboard.h"
44 #include "core/os/os.h"
45 #include "core/path_remap.h"
46 #include "core/print_string.h"
47 #include "core/project_settings.h"
48 #include "core/translation.h"
49 #include "core/version.h"
50 #include "main/input_default.h"
51 #include "main/main.h"
52 #include "scene/gui/center_container.h"
53 #include "scene/gui/control.h"
54 #include "scene/gui/dialogs.h"
55 #include "scene/gui/file_dialog.h"
56 #include "scene/gui/menu_button.h"
57 #include "scene/gui/panel.h"
58 #include "scene/gui/panel_container.h"
59 #include "scene/gui/split_container.h"
60 #include "scene/gui/tab_container.h"
61 #include "scene/gui/tabs.h"
62 #include "scene/gui/texture_progress.h"
63 #include "scene/gui/tool_button.h"
64 #include "scene/resources/packed_scene.h"
65 #include "servers/physics_2d_server.h"
66 
67 #include "editor/audio_stream_preview.h"
68 #include "editor/dependency_editor.h"
69 #include "editor/editor_about.h"
70 #include "editor/editor_audio_buses.h"
71 #include "editor/editor_export.h"
72 #include "editor/editor_feature_profile.h"
73 #include "editor/editor_file_system.h"
74 #include "editor/editor_help.h"
75 #include "editor/editor_inspector.h"
76 #include "editor/editor_layouts_dialog.h"
77 #include "editor/editor_log.h"
78 #include "editor/editor_plugin.h"
79 #include "editor/editor_properties.h"
80 #include "editor/editor_resource_preview.h"
81 #include "editor/editor_run_native.h"
82 #include "editor/editor_run_script.h"
83 #include "editor/editor_scale.h"
84 #include "editor/editor_settings.h"
85 #include "editor/editor_spin_slider.h"
86 #include "editor/editor_themes.h"
87 #include "editor/export_template_manager.h"
88 #include "editor/fileserver/editor_file_server.h"
89 #include "editor/filesystem_dock.h"
90 #include "editor/import/editor_import_collada.h"
91 #include "editor/import/editor_scene_importer_gltf.h"
92 #include "editor/import/resource_importer_bitmask.h"
93 #include "editor/import/resource_importer_csv.h"
94 #include "editor/import/resource_importer_csv_translation.h"
95 #include "editor/import/resource_importer_image.h"
96 #include "editor/import/resource_importer_layered_texture.h"
97 #include "editor/import/resource_importer_obj.h"
98 #include "editor/import/resource_importer_scene.h"
99 #include "editor/import/resource_importer_texture.h"
100 #include "editor/import/resource_importer_texture_atlas.h"
101 #include "editor/import/resource_importer_wav.h"
102 #include "editor/import_dock.h"
103 #include "editor/multi_node_edit.h"
104 #include "editor/node_dock.h"
105 #include "editor/pane_drag.h"
106 #include "editor/plugin_config_dialog.h"
107 #include "editor/plugins/animation_blend_space_1d_editor.h"
108 #include "editor/plugins/animation_blend_space_2d_editor.h"
109 #include "editor/plugins/animation_blend_tree_editor_plugin.h"
110 #include "editor/plugins/animation_player_editor_plugin.h"
111 #include "editor/plugins/animation_state_machine_editor.h"
112 #include "editor/plugins/animation_tree_editor_plugin.h"
113 #include "editor/plugins/animation_tree_player_editor_plugin.h"
114 #include "editor/plugins/asset_library_editor_plugin.h"
115 #include "editor/plugins/audio_stream_editor_plugin.h"
116 #include "editor/plugins/baked_lightmap_editor_plugin.h"
117 #include "editor/plugins/camera_editor_plugin.h"
118 #include "editor/plugins/canvas_item_editor_plugin.h"
119 #include "editor/plugins/collision_polygon_2d_editor_plugin.h"
120 #include "editor/plugins/collision_polygon_editor_plugin.h"
121 #include "editor/plugins/collision_shape_2d_editor_plugin.h"
122 #include "editor/plugins/cpu_particles_2d_editor_plugin.h"
123 #include "editor/plugins/cpu_particles_editor_plugin.h"
124 #include "editor/plugins/curve_editor_plugin.h"
125 #include "editor/plugins/editor_preview_plugins.h"
126 #include "editor/plugins/gi_probe_editor_plugin.h"
127 #include "editor/plugins/gradient_editor_plugin.h"
128 #include "editor/plugins/item_list_editor_plugin.h"
129 #include "editor/plugins/light_occluder_2d_editor_plugin.h"
130 #include "editor/plugins/line_2d_editor_plugin.h"
131 #include "editor/plugins/material_editor_plugin.h"
132 #include "editor/plugins/mesh_editor_plugin.h"
133 #include "editor/plugins/mesh_instance_editor_plugin.h"
134 #include "editor/plugins/mesh_library_editor_plugin.h"
135 #include "editor/plugins/multimesh_editor_plugin.h"
136 #include "editor/plugins/navigation_polygon_editor_plugin.h"
137 #include "editor/plugins/particles_2d_editor_plugin.h"
138 #include "editor/plugins/particles_editor_plugin.h"
139 #include "editor/plugins/path_2d_editor_plugin.h"
140 #include "editor/plugins/path_editor_plugin.h"
141 #include "editor/plugins/physical_bone_plugin.h"
142 #include "editor/plugins/polygon_2d_editor_plugin.h"
143 #include "editor/plugins/resource_preloader_editor_plugin.h"
144 #include "editor/plugins/root_motion_editor_plugin.h"
145 #include "editor/plugins/script_editor_plugin.h"
146 #include "editor/plugins/script_text_editor.h"
147 #include "editor/plugins/shader_editor_plugin.h"
148 #include "editor/plugins/skeleton_2d_editor_plugin.h"
149 #include "editor/plugins/skeleton_editor_plugin.h"
150 #include "editor/plugins/skeleton_ik_editor_plugin.h"
151 #include "editor/plugins/spatial_editor_plugin.h"
152 #include "editor/plugins/sprite_editor_plugin.h"
153 #include "editor/plugins/sprite_frames_editor_plugin.h"
154 #include "editor/plugins/style_box_editor_plugin.h"
155 #include "editor/plugins/text_editor.h"
156 #include "editor/plugins/texture_editor_plugin.h"
157 #include "editor/plugins/texture_region_editor_plugin.h"
158 #include "editor/plugins/theme_editor_plugin.h"
159 #include "editor/plugins/tile_map_editor_plugin.h"
160 #include "editor/plugins/tile_set_editor_plugin.h"
161 #include "editor/plugins/version_control_editor_plugin.h"
162 #include "editor/plugins/visual_shader_editor_plugin.h"
163 #include "editor/progress_dialog.h"
164 #include "editor/project_export.h"
165 #include "editor/project_settings_editor.h"
166 #include "editor/pvrtc_compress.h"
167 #include "editor/quick_open.h"
168 #include "editor/register_exporters.h"
169 #include "editor/run_settings_dialog.h"
170 #include "editor/script_editor_debugger.h"
171 #include "editor/settings_config_dialog.h"
172 
173 #include <stdio.h>
174 #include <stdlib.h>
175 
176 EditorNode *EditorNode::singleton = NULL;
177 
disambiguate_filenames(const Vector<String> p_full_paths,Vector<String> & r_filenames)178 void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames) {
179 	// Keep track of a list of "index sets," i.e. sets of indices
180 	// within disambiguated_scene_names which contain the same name.
181 	Vector<Set<int> > index_sets;
182 	Map<String, int> scene_name_to_set_index;
183 	for (int i = 0; i < r_filenames.size(); i++) {
184 		String scene_name = r_filenames[i];
185 		if (!scene_name_to_set_index.has(scene_name)) {
186 			index_sets.push_back(Set<int>());
187 			scene_name_to_set_index.insert(r_filenames[i], index_sets.size() - 1);
188 		}
189 		index_sets.write[scene_name_to_set_index[scene_name]].insert(i);
190 	}
191 
192 	// For each index set with a size > 1, we need to disambiguate
193 	for (int i = 0; i < index_sets.size(); i++) {
194 		Set<int> iset = index_sets[i];
195 		while (iset.size() > 1) {
196 			// Append the parent folder to each scene name
197 			for (Set<int>::Element *E = iset.front(); E; E = E->next()) {
198 				int set_idx = E->get();
199 				String scene_name = r_filenames[set_idx];
200 				String full_path = p_full_paths[set_idx];
201 
202 				// Get rid of file extensions and res:// prefixes
203 				if (scene_name.rfind(".") >= 0) {
204 					scene_name = scene_name.substr(0, scene_name.rfind("."));
205 				}
206 				if (full_path.begins_with("res://")) {
207 					full_path = full_path.substr(6);
208 				}
209 				if (full_path.rfind(".") >= 0) {
210 					full_path = full_path.substr(0, full_path.rfind("."));
211 				}
212 
213 				int scene_name_size = scene_name.size();
214 				int full_path_size = full_path.size();
215 				int difference = full_path_size - scene_name_size;
216 
217 				// Find just the parent folder of the current path and append it.
218 				// If the current name is foo.tscn, and the full path is /some/folder/foo.tscn
219 				// then slash_idx is the second '/', so that we select just "folder", and
220 				// append that to yield "folder/foo.tscn".
221 				if (difference > 0) {
222 					String parent = full_path.substr(0, difference);
223 					int slash_idx = parent.rfind("/");
224 					slash_idx = parent.rfind("/", slash_idx - 1);
225 					parent = slash_idx >= 0 ? parent.substr(slash_idx + 1) : parent;
226 					r_filenames.write[set_idx] = parent + r_filenames[set_idx];
227 				}
228 			}
229 
230 			// Loop back through scene names and remove non-ambiguous names
231 			bool can_proceed = false;
232 			Set<int>::Element *E = iset.front();
233 			while (E) {
234 				String scene_name = r_filenames[E->get()];
235 				bool duplicate_found = false;
236 				for (Set<int>::Element *F = iset.front(); F; F = F->next()) {
237 					if (E->get() == F->get()) {
238 						continue;
239 					}
240 					String other_scene_name = r_filenames[F->get()];
241 					if (other_scene_name == scene_name) {
242 						duplicate_found = true;
243 						break;
244 					}
245 				}
246 
247 				Set<int>::Element *to_erase = duplicate_found ? nullptr : E;
248 
249 				// We need to check that we could actually append anymore names
250 				// if we wanted to for disambiguation. If we can't, then we have
251 				// to abort even with ambiguous names. We clean the full path
252 				// and the scene name first to remove extensions so that this
253 				// comparison actually works.
254 				String path = p_full_paths[E->get()];
255 				if (path.begins_with("res://")) {
256 					path = path.substr(6);
257 				}
258 				if (path.rfind(".") >= 0) {
259 					path = path.substr(0, path.rfind("."));
260 				}
261 				if (scene_name.rfind(".") >= 0) {
262 					scene_name = scene_name.substr(0, scene_name.rfind("."));
263 				}
264 
265 				// We can proceed iff the full path is longer than the scene name,
266 				// meaning that there is at least one more parent folder we can
267 				// tack onto the name.
268 				can_proceed = can_proceed || (path.size() - scene_name.size()) >= 1;
269 
270 				E = E->next();
271 				if (to_erase) {
272 					iset.erase(to_erase);
273 				}
274 			}
275 
276 			if (!can_proceed) {
277 				break;
278 			}
279 		}
280 	}
281 }
282 
_update_scene_tabs()283 void EditorNode::_update_scene_tabs() {
284 
285 	bool show_rb = EditorSettings::get_singleton()->get("interface/scene_tabs/show_script_button");
286 
287 	OS::get_singleton()->global_menu_clear("_dock");
288 
289 	// Get all scene names, which may be ambiguous
290 	Vector<String> disambiguated_scene_names;
291 	Vector<String> full_path_names;
292 	for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
293 		disambiguated_scene_names.push_back(editor_data.get_scene_title(i));
294 		full_path_names.push_back(editor_data.get_scene_path(i));
295 	}
296 
297 	disambiguate_filenames(full_path_names, disambiguated_scene_names);
298 
299 	scene_tabs->clear_tabs();
300 	Ref<Texture> script_icon = gui_base->get_icon("Script", "EditorIcons");
301 	for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
302 
303 		Node *type_node = editor_data.get_edited_scene_root(i);
304 		Ref<Texture> icon;
305 		if (type_node) {
306 			icon = EditorNode::get_singleton()->get_object_icon(type_node, "Node");
307 		}
308 
309 		int current = editor_data.get_edited_scene();
310 		bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0;
311 		scene_tabs->add_tab(disambiguated_scene_names[i] + (unsaved ? "(*)" : ""), icon);
312 
313 		OS::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), GLOBAL_SCENE, i);
314 
315 		if (show_rb && editor_data.get_scene_root_script(i).is_valid()) {
316 			scene_tabs->set_tab_right_button(i, script_icon);
317 		}
318 	}
319 
320 	OS::get_singleton()->global_menu_add_separator("_dock");
321 	OS::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant());
322 
323 	scene_tabs->set_current_tab(editor_data.get_edited_scene());
324 
325 	if (scene_tabs->get_offset_buttons_visible()) {
326 		// move add button to fixed position on the tabbar
327 		if (scene_tab_add->get_parent() == scene_tabs) {
328 			scene_tab_add->set_position(Point2(0, 0));
329 			scene_tabs->remove_child(scene_tab_add);
330 			tabbar_container->add_child(scene_tab_add);
331 			tabbar_container->move_child(scene_tab_add, 1);
332 		}
333 	} else {
334 		// move add button to after last tab
335 		if (scene_tab_add->get_parent() == tabbar_container) {
336 			tabbar_container->remove_child(scene_tab_add);
337 			scene_tabs->add_child(scene_tab_add);
338 		}
339 		Rect2 last_tab = Rect2();
340 		if (scene_tabs->get_tab_count() != 0)
341 			last_tab = scene_tabs->get_tab_rect(scene_tabs->get_tab_count() - 1);
342 		scene_tab_add->set_position(Point2(last_tab.get_position().x + last_tab.get_size().x + 3, last_tab.get_position().y));
343 	}
344 }
345 
_version_control_menu_option(int p_idx)346 void EditorNode::_version_control_menu_option(int p_idx) {
347 
348 	switch (vcs_actions_menu->get_item_id(p_idx)) {
349 		case RUN_VCS_SETTINGS: {
350 
351 			VersionControlEditorPlugin::get_singleton()->popup_vcs_set_up_dialog(gui_base);
352 		} break;
353 		case RUN_VCS_SHUT_DOWN: {
354 
355 			VersionControlEditorPlugin::get_singleton()->shut_down();
356 		} break;
357 	}
358 }
359 
_update_title()360 void EditorNode::_update_title() {
361 
362 	String appname = ProjectSettings::get_singleton()->get("application/config/name");
363 	String title = appname.empty() ? String(VERSION_FULL_NAME) : String(VERSION_NAME + String(" - ") + appname);
364 	String edited = editor_data.get_edited_scene_root() ? editor_data.get_edited_scene_root()->get_filename() : String();
365 	if (!edited.empty())
366 		title += " - " + String(edited.get_file());
367 	if (unsaved_cache)
368 		title += " (*)";
369 
370 	OS::get_singleton()->set_window_title(title);
371 }
372 
_unhandled_input(const Ref<InputEvent> & p_event)373 void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) {
374 
375 	if (Node::get_viewport()->get_modal_stack_top())
376 		return; //ignore because of modal window
377 
378 	Ref<InputEventKey> k = p_event;
379 	if (k.is_valid() && k->is_pressed() && !k->is_echo() && !gui_base->get_viewport()->gui_has_modal_stack()) {
380 
381 		EditorPlugin *old_editor = editor_plugin_screen;
382 
383 		if (ED_IS_SHORTCUT("editor/next_tab", p_event)) {
384 			int next_tab = editor_data.get_edited_scene() + 1;
385 			next_tab %= editor_data.get_edited_scene_count();
386 			_scene_tab_changed(next_tab);
387 		}
388 		if (ED_IS_SHORTCUT("editor/prev_tab", p_event)) {
389 			int next_tab = editor_data.get_edited_scene() - 1;
390 			next_tab = next_tab >= 0 ? next_tab : editor_data.get_edited_scene_count() - 1;
391 			_scene_tab_changed(next_tab);
392 		}
393 		if (ED_IS_SHORTCUT("editor/filter_files", p_event)) {
394 			filesystem_dock->focus_on_filter();
395 		}
396 
397 		if (ED_IS_SHORTCUT("editor/editor_2d", p_event)) {
398 			_editor_select(EDITOR_2D);
399 		} else if (ED_IS_SHORTCUT("editor/editor_3d", p_event)) {
400 			_editor_select(EDITOR_3D);
401 		} else if (ED_IS_SHORTCUT("editor/editor_script", p_event)) {
402 			_editor_select(EDITOR_SCRIPT);
403 		} else if (ED_IS_SHORTCUT("editor/editor_help", p_event)) {
404 			emit_signal("request_help_search", "");
405 		} else if (ED_IS_SHORTCUT("editor/editor_assetlib", p_event) && StreamPeerSSL::is_available()) {
406 			_editor_select(EDITOR_ASSETLIB);
407 		} else if (ED_IS_SHORTCUT("editor/editor_next", p_event)) {
408 			_editor_select_next();
409 		} else if (ED_IS_SHORTCUT("editor/editor_prev", p_event)) {
410 			_editor_select_prev();
411 		}
412 
413 		if (old_editor != editor_plugin_screen) {
414 			get_tree()->set_input_as_handled();
415 		}
416 	}
417 }
418 
_notification(int p_what)419 void EditorNode::_notification(int p_what) {
420 
421 	switch (p_what) {
422 		case NOTIFICATION_PROCESS: {
423 			if (opening_prev && !confirmation->is_visible())
424 				opening_prev = false;
425 
426 			if (unsaved_cache != (saved_version != editor_data.get_undo_redo().get_version())) {
427 
428 				unsaved_cache = (saved_version != editor_data.get_undo_redo().get_version());
429 				_update_title();
430 			}
431 
432 			if (last_checked_version != editor_data.get_undo_redo().get_version()) {
433 				_update_scene_tabs();
434 				last_checked_version = editor_data.get_undo_redo().get_version();
435 			}
436 
437 			// update the animation frame of the update spinner
438 			uint64_t frame = Engine::get_singleton()->get_frames_drawn();
439 			uint32_t tick = OS::get_singleton()->get_ticks_msec();
440 
441 			if (frame != update_spinner_step_frame && (tick - update_spinner_step_msec) > (1000 / 8)) {
442 
443 				update_spinner_step++;
444 				if (update_spinner_step >= 8)
445 					update_spinner_step = 0;
446 
447 				update_spinner_step_msec = tick;
448 				update_spinner_step_frame = frame + 1;
449 
450 				// update the icon itself only when the spinner is visible
451 				if (EditorSettings::get_singleton()->get("interface/editor/show_update_spinner")) {
452 					update_spinner->set_icon(gui_base->get_icon("Progress" + itos(update_spinner_step + 1), "EditorIcons"));
453 				}
454 			}
455 
456 			editor_selection->update();
457 
458 			scene_root->set_size_override(true, Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")));
459 
460 			ResourceImporterTexture::get_singleton()->update_imports();
461 		} break;
462 
463 		case NOTIFICATION_ENTER_TREE: {
464 			Engine::get_singleton()->set_editor_hint(true);
465 
466 			OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec")));
467 			get_tree()->get_root()->set_usage(Viewport::USAGE_2D_NO_SAMPLING); //reduce memory usage
468 			get_tree()->get_root()->set_disable_3d(true);
469 			get_tree()->get_root()->set_as_audio_listener(false);
470 			get_tree()->get_root()->set_as_audio_listener_2d(false);
471 			get_tree()->set_auto_accept_quit(false);
472 			get_tree()->connect("files_dropped", this, "_dropped_files");
473 			get_tree()->connect("global_menu_action", this, "_global_menu_action");
474 
475 			/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
476 		} break;
477 
478 		case NOTIFICATION_EXIT_TREE: {
479 			editor_data.save_editor_external_data();
480 			FileAccess::set_file_close_fail_notify_callback(NULL);
481 			log->deinit(); // do not get messages anymore
482 			editor_data.clear_edited_scenes();
483 		} break;
484 
485 		case NOTIFICATION_READY: {
486 
487 			{
488 				_initializing_addons = true;
489 				Vector<String> addons;
490 				if (ProjectSettings::get_singleton()->has_setting("editor_plugins/enabled")) {
491 					addons = ProjectSettings::get_singleton()->get("editor_plugins/enabled");
492 				}
493 
494 				for (int i = 0; i < addons.size(); i++) {
495 					set_addon_plugin_enabled(addons[i], true);
496 				}
497 				_initializing_addons = false;
498 			}
499 
500 			VisualServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport_rid(), true);
501 			VisualServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport_rid(), true);
502 			VisualServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(), true);
503 
504 			feature_profile_manager->notify_changed();
505 
506 			if (!main_editor_buttons[EDITOR_3D]->is_visible()) { //may be hidden due to feature profile
507 				_editor_select(EDITOR_2D);
508 			} else {
509 				_editor_select(EDITOR_3D);
510 			}
511 
512 			_update_debug_options();
513 
514 			/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
515 		} break;
516 
517 		case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
518 
519 			// Restore the original FPS cap after focusing back on the editor
520 			OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec")));
521 
522 			EditorFileSystem::get_singleton()->scan_changes();
523 		} break;
524 
525 		case MainLoop::NOTIFICATION_WM_FOCUS_OUT: {
526 
527 			// Set a low FPS cap to decrease CPU/GPU usage while the editor is unfocused
528 			OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/unfocused_low_processor_mode_sleep_usec")));
529 		} break;
530 
531 		case MainLoop::NOTIFICATION_WM_ABOUT: {
532 
533 			show_about();
534 		} break;
535 
536 		case MainLoop::NOTIFICATION_WM_QUIT_REQUEST: {
537 
538 			_menu_option_confirm(FILE_QUIT, false);
539 		} break;
540 
541 		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
542 			scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
543 			theme = create_editor_theme(theme_base->get_theme());
544 
545 			theme_base->set_theme(theme);
546 			gui_base->set_theme(theme);
547 
548 			gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles"));
549 			scene_root_parent->add_style_override("panel", gui_base->get_stylebox("Content", "EditorStyles"));
550 			bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer"));
551 			scene_tabs->add_style_override("tab_fg", gui_base->get_stylebox("SceneTabFG", "EditorStyles"));
552 			scene_tabs->add_style_override("tab_bg", gui_base->get_stylebox("SceneTabBG", "EditorStyles"));
553 
554 			file_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
555 			project_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
556 			debug_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
557 			settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
558 			help_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
559 
560 			if (EDITOR_GET("interface/scene_tabs/resize_if_many_tabs")) {
561 				scene_tabs->set_min_width(int(EDITOR_GET("interface/scene_tabs/minimum_width")) * EDSCALE);
562 			} else {
563 				scene_tabs->set_min_width(0);
564 			}
565 			_update_scene_tabs();
566 
567 			recent_scenes->set_as_minsize();
568 
569 			// debugger area
570 			if (ScriptEditor::get_singleton()->get_debugger()->is_visible())
571 				bottom_panel->add_style_override("panel", gui_base->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles"));
572 
573 			// update_icons
574 			for (int i = 0; i < singleton->main_editor_buttons.size(); i++) {
575 
576 				ToolButton *tb = singleton->main_editor_buttons[i];
577 				EditorPlugin *p_editor = singleton->editor_table[i];
578 				Ref<Texture> icon = p_editor->get_icon();
579 
580 				if (icon.is_valid()) {
581 					tb->set_icon(icon);
582 				} else if (singleton->gui_base->has_icon(p_editor->get_name(), "EditorIcons")) {
583 					tb->set_icon(singleton->gui_base->get_icon(p_editor->get_name(), "EditorIcons"));
584 				}
585 			}
586 
587 			_build_icon_type_cache();
588 
589 			play_button->set_icon(gui_base->get_icon("MainPlay", "EditorIcons"));
590 			play_scene_button->set_icon(gui_base->get_icon("PlayScene", "EditorIcons"));
591 			play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons"));
592 			pause_button->set_icon(gui_base->get_icon("Pause", "EditorIcons"));
593 			stop_button->set_icon(gui_base->get_icon("Stop", "EditorIcons"));
594 
595 			prev_scene->set_icon(gui_base->get_icon("PrevScene", "EditorIcons"));
596 			distraction_free->set_icon(gui_base->get_icon("DistractionFree", "EditorIcons"));
597 			scene_tab_add->set_icon(gui_base->get_icon("Add", "EditorIcons"));
598 
599 			bottom_panel_raise->set_icon(gui_base->get_icon("ExpandBottomDock", "EditorIcons"));
600 
601 			// clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons")); don't have access to that node. needs to become a class property
602 			dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons"));
603 			dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons"));
604 
605 			PopupMenu *p = help_menu->get_popup();
606 			p->set_item_icon(p->get_item_index(HELP_SEARCH), gui_base->get_icon("HelpSearch", "EditorIcons"));
607 			p->set_item_icon(p->get_item_index(HELP_DOCS), gui_base->get_icon("Instance", "EditorIcons"));
608 			p->set_item_icon(p->get_item_index(HELP_QA), gui_base->get_icon("Instance", "EditorIcons"));
609 			p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_icon("Godot", "EditorIcons"));
610 			p->set_item_icon(p->get_item_index(HELP_REPORT_A_BUG), gui_base->get_icon("Instance", "EditorIcons"));
611 			p->set_item_icon(p->get_item_index(HELP_SEND_DOCS_FEEDBACK), gui_base->get_icon("Instance", "EditorIcons"));
612 			p->set_item_icon(p->get_item_index(HELP_COMMUNITY), gui_base->get_icon("Instance", "EditorIcons"));
613 			p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_icon("Godot", "EditorIcons"));
614 
615 			_update_update_spinner();
616 		} break;
617 
618 		case Control::NOTIFICATION_RESIZED: {
619 			_update_scene_tabs();
620 		} break;
621 	}
622 }
623 
_update_update_spinner()624 void EditorNode::_update_update_spinner() {
625 	update_spinner->set_visible(EditorSettings::get_singleton()->get("interface/editor/show_update_spinner"));
626 
627 	bool update_continuously = EditorSettings::get_singleton()->get("interface/editor/update_continuously");
628 	PopupMenu *update_popup = update_spinner->get_popup();
629 	update_popup->set_item_checked(update_popup->get_item_index(SETTINGS_UPDATE_CONTINUOUSLY), update_continuously);
630 	update_popup->set_item_checked(update_popup->get_item_index(SETTINGS_UPDATE_WHEN_CHANGED), !update_continuously);
631 
632 	OS::get_singleton()->set_low_processor_usage_mode(!update_continuously);
633 }
634 
_on_plugin_ready(Object * p_script,const String & p_activate_name)635 void EditorNode::_on_plugin_ready(Object *p_script, const String &p_activate_name) {
636 	Ref<Script> script = Object::cast_to<Script>(p_script);
637 	if (script.is_null())
638 		return;
639 	if (p_activate_name.length()) {
640 		set_addon_plugin_enabled(p_activate_name, true);
641 	}
642 	project_settings->update_plugins();
643 	project_settings->hide();
644 	push_item(script.operator->());
645 }
646 
_resources_changed(const PoolVector<String> & p_resources)647 void EditorNode::_resources_changed(const PoolVector<String> &p_resources) {
648 
649 	List<Ref<Resource> > changed;
650 
651 	int rc = p_resources.size();
652 	for (int i = 0; i < rc; i++) {
653 
654 		Ref<Resource> res(ResourceCache::get(p_resources.get(i)));
655 		if (res.is_null()) {
656 			continue;
657 		}
658 
659 		if (!res->editor_can_reload_from_file())
660 			continue;
661 		if (!res->get_path().is_resource_file() && !res->get_path().is_abs_path())
662 			continue;
663 		if (!FileAccess::exists(res->get_path()))
664 			continue;
665 
666 		if (res->get_import_path() != String()) {
667 			//this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback
668 			continue;
669 		}
670 
671 		changed.push_back(res);
672 	}
673 
674 	if (changed.size()) {
675 		for (List<Ref<Resource> >::Element *E = changed.front(); E; E = E->next()) {
676 			E->get()->reload_from_file();
677 		}
678 	}
679 }
680 
_fs_changed()681 void EditorNode::_fs_changed() {
682 
683 	for (Set<FileDialog *>::Element *E = file_dialogs.front(); E; E = E->next()) {
684 
685 		E->get()->invalidate();
686 	}
687 
688 	for (Set<EditorFileDialog *>::Element *E = editor_file_dialogs.front(); E; E = E->next()) {
689 
690 		E->get()->invalidate();
691 	}
692 
693 	_mark_unsaved_scenes();
694 
695 	// FIXME: Move this to a cleaner location, it's hacky to do this is _fs_changed.
696 	String export_error;
697 	if (export_defer.preset != "" && !EditorFileSystem::get_singleton()->is_scanning()) {
698 		String preset_name = export_defer.preset;
699 		// Ensures export_project does not loop infinitely, because notifications may
700 		// come during the export.
701 		export_defer.preset = "";
702 		Ref<EditorExportPreset> preset;
703 		for (int i = 0; i < EditorExport::get_singleton()->get_export_preset_count(); ++i) {
704 			preset = EditorExport::get_singleton()->get_export_preset(i);
705 			if (preset->get_name() == preset_name) {
706 				break;
707 			}
708 			preset.unref();
709 		}
710 		if (preset.is_null()) {
711 			export_error = vformat(
712 					"Invalid export preset name: %s. Make sure `export_presets.cfg` is present in the current directory.",
713 					preset_name);
714 		} else {
715 			Ref<EditorExportPlatform> platform = preset->get_platform();
716 			if (platform.is_null()) {
717 				export_error = vformat("Export preset '%s' doesn't have a matching platform.", preset_name);
718 			} else {
719 				Error err = OK;
720 				if (export_defer.pack_only) { // Only export .pck or .zip data pack.
721 					if (export_defer.path.ends_with(".zip")) {
722 						err = platform->export_zip(preset, export_defer.debug, export_defer.path);
723 					} else if (export_defer.path.ends_with(".pck")) {
724 						err = platform->export_pack(preset, export_defer.debug, export_defer.path);
725 					}
726 				} else { // Normal project export.
727 					String config_error;
728 					bool missing_templates;
729 					if (!platform->can_export(preset, config_error, missing_templates)) {
730 						ERR_PRINT(vformat("Cannot export project with preset '%s' due to configuration errors:\n%s", preset_name, config_error));
731 						err = missing_templates ? ERR_FILE_NOT_FOUND : ERR_UNCONFIGURED;
732 					} else {
733 						err = platform->export_project(preset, export_defer.debug, export_defer.path);
734 					}
735 				}
736 				switch (err) {
737 					case OK:
738 						break;
739 					case ERR_FILE_NOT_FOUND:
740 						export_error = vformat("Project export failed for preset '%s', the export template appears to be missing.", preset_name);
741 						break;
742 					case ERR_FILE_BAD_PATH:
743 						export_error = vformat("Project export failed for preset '%s', the target path '%s' appears to be invalid.", preset_name, export_defer.path);
744 						break;
745 					default:
746 						export_error = vformat("Project export failed with error code %d for preset '%s'.", (int)err, preset_name);
747 						break;
748 				}
749 			}
750 		}
751 
752 		if (!export_error.empty()) {
753 			ERR_PRINT(export_error);
754 			OS::get_singleton()->set_exit_code(EXIT_FAILURE);
755 		}
756 		_exit_editor();
757 	}
758 }
759 
_resources_reimported(const Vector<String> & p_resources)760 void EditorNode::_resources_reimported(const Vector<String> &p_resources) {
761 
762 	List<String> scenes; //will load later
763 	int current_tab = scene_tabs->get_current_tab();
764 
765 	for (int i = 0; i < p_resources.size(); i++) {
766 		String file_type = ResourceLoader::get_resource_type(p_resources[i]);
767 		if (file_type == "PackedScene") {
768 			scenes.push_back(p_resources[i]);
769 			//reload later if needed, first go with normal resources
770 			continue;
771 		}
772 
773 		if (!ResourceCache::has(p_resources[i])) {
774 			continue; //not loaded, no need to reload
775 		}
776 		//reload normally
777 		Resource *resource = ResourceCache::get(p_resources[i]);
778 		if (resource) {
779 			resource->reload_from_file();
780 		}
781 	}
782 
783 	for (List<String>::Element *E = scenes.front(); E; E = E->next()) {
784 		reload_scene(E->get());
785 	}
786 
787 	scene_tabs->set_current_tab(current_tab);
788 }
789 
_sources_changed(bool p_exist)790 void EditorNode::_sources_changed(bool p_exist) {
791 
792 	if (waiting_for_first_scan) {
793 		waiting_for_first_scan = false;
794 
795 		// Start preview thread now that it's safe.
796 		if (!singleton->cmdline_export_mode) {
797 			EditorResourcePreview::get_singleton()->start();
798 		}
799 
800 		_load_docks();
801 
802 		if (defer_load_scene != "") {
803 			load_scene(defer_load_scene);
804 			defer_load_scene = "";
805 		}
806 	}
807 }
808 
_vp_resized()809 void EditorNode::_vp_resized() {
810 }
811 
_node_renamed()812 void EditorNode::_node_renamed() {
813 
814 	if (get_inspector())
815 		get_inspector()->update_tree();
816 }
817 
_editor_select_next()818 void EditorNode::_editor_select_next() {
819 
820 	int editor = _get_current_main_editor();
821 
822 	do {
823 		if (editor == editor_table.size() - 1) {
824 			editor = 0;
825 		} else {
826 			editor++;
827 		}
828 	} while (!main_editor_buttons[editor]->is_visible());
829 
830 	_editor_select(editor);
831 }
832 
_editor_select_prev()833 void EditorNode::_editor_select_prev() {
834 
835 	int editor = _get_current_main_editor();
836 
837 	do {
838 		if (editor == 0) {
839 			editor = editor_table.size() - 1;
840 		} else {
841 			editor--;
842 		}
843 	} while (!main_editor_buttons[editor]->is_visible());
844 
845 	_editor_select(editor);
846 }
847 
load_resource(const String & p_resource,bool p_ignore_broken_deps)848 Error EditorNode::load_resource(const String &p_resource, bool p_ignore_broken_deps) {
849 
850 	dependency_errors.clear();
851 
852 	Error err;
853 	RES res = ResourceLoader::load(p_resource, "", false, &err);
854 	ERR_FAIL_COND_V(!res.is_valid(), ERR_CANT_OPEN);
855 
856 	if (!p_ignore_broken_deps && dependency_errors.has(p_resource)) {
857 
858 		//current_option = -1;
859 		Vector<String> errors;
860 		for (Set<String>::Element *E = dependency_errors[p_resource].front(); E; E = E->next()) {
861 
862 			errors.push_back(E->get());
863 		}
864 		dependency_error->show(DependencyErrorDialog::MODE_RESOURCE, p_resource, errors);
865 		dependency_errors.erase(p_resource);
866 
867 		return ERR_FILE_MISSING_DEPENDENCIES;
868 	}
869 
870 	inspector_dock->edit_resource(res);
871 	return OK;
872 }
873 
edit_node(Node * p_node)874 void EditorNode::edit_node(Node *p_node) {
875 
876 	push_item(p_node);
877 }
878 
save_resource_in_path(const Ref<Resource> & p_resource,const String & p_path)879 void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path) {
880 
881 	editor_data.apply_changes_in_editors();
882 	int flg = 0;
883 	if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources"))
884 		flg |= ResourceSaver::FLAG_COMPRESS;
885 
886 	String path = ProjectSettings::get_singleton()->localize_path(p_path);
887 	Error err = ResourceSaver::save(path, p_resource, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
888 
889 	if (err != OK) {
890 		if (ResourceLoader::is_imported(p_resource->get_path())) {
891 			show_accept(TTR("Imported resources can't be saved."), TTR("OK"));
892 		} else {
893 			show_accept(TTR("Error saving resource!"), TTR("OK"));
894 		}
895 		return;
896 	}
897 
898 	((Resource *)p_resource.ptr())->set_path(path);
899 	emit_signal("resource_saved", p_resource);
900 	editor_data.notify_resource_saved(p_resource);
901 }
902 
save_resource(const Ref<Resource> & p_resource)903 void EditorNode::save_resource(const Ref<Resource> &p_resource) {
904 
905 	if (p_resource->get_path().is_resource_file()) {
906 		save_resource_in_path(p_resource, p_resource->get_path());
907 	} else {
908 		save_resource_as(p_resource);
909 	}
910 }
911 
save_resource_as(const Ref<Resource> & p_resource,const String & p_at_path)912 void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String &p_at_path) {
913 
914 	{
915 		String path = p_resource->get_path();
916 		int srpos = path.find("::");
917 		if (srpos != -1) {
918 			String base = path.substr(0, srpos);
919 			if (!get_edited_scene() || get_edited_scene()->get_filename() != base) {
920 				show_warning(TTR("This resource can't be saved because it does not belong to the edited scene. Make it unique first."));
921 				return;
922 			}
923 		}
924 	}
925 
926 	file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
927 	saving_resource = p_resource;
928 
929 	current_option = RESOURCE_SAVE_AS;
930 	List<String> extensions;
931 	Ref<PackedScene> sd = memnew(PackedScene);
932 	ResourceSaver::get_recognized_extensions(p_resource, &extensions);
933 	file->clear_filters();
934 
935 	List<String> preferred;
936 	for (int i = 0; i < extensions.size(); i++) {
937 
938 		if (p_resource->is_class("Script") && (extensions[i] == "tres" || extensions[i] == "res" || extensions[i] == "xml")) {
939 			//this serves no purpose and confused people
940 			continue;
941 		}
942 		file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
943 		preferred.push_back(extensions[i]);
944 	}
945 
946 	if (p_at_path != String()) {
947 
948 		file->set_current_dir(p_at_path);
949 		if (p_resource->get_path().is_resource_file()) {
950 			file->set_current_file(p_resource->get_path().get_file());
951 		} else {
952 			if (extensions.size()) {
953 				file->set_current_file("new_" + p_resource->get_class().to_lower() + "." + preferred.front()->get().to_lower());
954 			} else {
955 				file->set_current_file(String());
956 			}
957 		}
958 	} else if (p_resource->get_path() != "") {
959 
960 		file->set_current_path(p_resource->get_path());
961 		if (extensions.size()) {
962 			String ext = p_resource->get_path().get_extension().to_lower();
963 			if (extensions.find(ext) == NULL) {
964 				file->set_current_path(p_resource->get_path().replacen("." + ext, "." + extensions.front()->get()));
965 			}
966 		}
967 	} else if (preferred.size()) {
968 
969 		String existing;
970 		if (extensions.size()) {
971 			existing = "new_" + p_resource->get_class().to_lower() + "." + preferred.front()->get().to_lower();
972 		}
973 		file->set_current_path(existing);
974 	}
975 	file->popup_centered_ratio();
976 	file->set_title(TTR("Save Resource As..."));
977 }
978 
_menu_option(int p_option)979 void EditorNode::_menu_option(int p_option) {
980 
981 	_menu_option_confirm(p_option, false);
982 }
983 
_menu_confirm_current()984 void EditorNode::_menu_confirm_current() {
985 
986 	_menu_option_confirm(current_option, true);
987 }
988 
_dialog_display_save_error(String p_file,Error p_error)989 void EditorNode::_dialog_display_save_error(String p_file, Error p_error) {
990 
991 	if (p_error) {
992 
993 		switch (p_error) {
994 
995 			case ERR_FILE_CANT_WRITE: {
996 
997 				show_accept(TTR("Can't open file for writing:") + " " + p_file.get_extension(), TTR("OK"));
998 			} break;
999 			case ERR_FILE_UNRECOGNIZED: {
1000 
1001 				show_accept(TTR("Requested file format unknown:") + " " + p_file.get_extension(), TTR("OK"));
1002 			} break;
1003 			default: {
1004 
1005 				show_accept(TTR("Error while saving."), TTR("OK"));
1006 			} break;
1007 		}
1008 	}
1009 }
1010 
_dialog_display_load_error(String p_file,Error p_error)1011 void EditorNode::_dialog_display_load_error(String p_file, Error p_error) {
1012 
1013 	if (p_error) {
1014 
1015 		switch (p_error) {
1016 
1017 			case ERR_CANT_OPEN: {
1018 
1019 				show_accept(vformat(TTR("Can't open '%s'. The file could have been moved or deleted."), p_file.get_file()), TTR("OK"));
1020 			} break;
1021 			case ERR_PARSE_ERROR: {
1022 
1023 				show_accept(vformat(TTR("Error while parsing '%s'."), p_file.get_file()), TTR("OK"));
1024 			} break;
1025 			case ERR_FILE_CORRUPT: {
1026 
1027 				show_accept(vformat(TTR("Unexpected end of file '%s'."), p_file.get_file()), TTR("OK"));
1028 			} break;
1029 			case ERR_FILE_NOT_FOUND: {
1030 
1031 				show_accept(vformat(TTR("Missing '%s' or its dependencies."), p_file.get_file()), TTR("OK"));
1032 			} break;
1033 			default: {
1034 
1035 				show_accept(vformat(TTR("Error while loading '%s'."), p_file.get_file()), TTR("OK"));
1036 			} break;
1037 		}
1038 	}
1039 }
1040 
_get_scene_metadata(const String & p_file)1041 void EditorNode::_get_scene_metadata(const String &p_file) {
1042 
1043 	Node *scene = editor_data.get_edited_scene_root();
1044 
1045 	if (!scene)
1046 		return;
1047 
1048 	String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
1049 
1050 	Ref<ConfigFile> cf;
1051 	cf.instance();
1052 
1053 	Error err = cf->load(path);
1054 	if (err != OK || !cf->has_section("editor_states"))
1055 		return; //must not exist
1056 
1057 	List<String> esl;
1058 	cf->get_section_keys("editor_states", &esl);
1059 
1060 	Dictionary md;
1061 	for (List<String>::Element *E = esl.front(); E; E = E->next()) {
1062 
1063 		Variant st = cf->get_value("editor_states", E->get());
1064 		if (st.get_type() != Variant::NIL) {
1065 			md[E->get()] = st;
1066 		}
1067 	}
1068 
1069 	editor_data.set_editor_states(md);
1070 }
1071 
_set_scene_metadata(const String & p_file,int p_idx)1072 void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) {
1073 
1074 	Node *scene = editor_data.get_edited_scene_root(p_idx);
1075 
1076 	if (!scene)
1077 		return;
1078 
1079 	scene->set_meta("__editor_run_settings__", Variant()); //clear it (no point in keeping it)
1080 	scene->set_meta("__editor_plugin_states__", Variant());
1081 
1082 	String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
1083 
1084 	Ref<ConfigFile> cf;
1085 	cf.instance();
1086 
1087 	Dictionary md;
1088 
1089 	if (p_idx < 0 || editor_data.get_edited_scene() == p_idx) {
1090 		md = editor_data.get_editor_states();
1091 	} else {
1092 		md = editor_data.get_scene_editor_states(p_idx);
1093 	}
1094 
1095 	List<Variant> keys;
1096 	md.get_key_list(&keys);
1097 
1098 	for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
1099 
1100 		cf->set_value("editor_states", E->get(), md[E->get()]);
1101 	}
1102 
1103 	Error err = cf->save(path);
1104 	ERR_FAIL_COND_MSG(err != OK, "Cannot save config file to '" + path + "'.");
1105 }
1106 
_find_and_save_resource(RES p_res,Map<RES,bool> & processed,int32_t flags)1107 bool EditorNode::_find_and_save_resource(RES p_res, Map<RES, bool> &processed, int32_t flags) {
1108 
1109 	if (p_res.is_null())
1110 		return false;
1111 
1112 	if (processed.has(p_res)) {
1113 
1114 		return processed[p_res];
1115 	}
1116 
1117 	bool changed = p_res->is_edited();
1118 	p_res->set_edited(false);
1119 
1120 	bool subchanged = _find_and_save_edited_subresources(p_res.ptr(), processed, flags);
1121 
1122 	if (p_res->get_path().is_resource_file()) {
1123 		if (changed || subchanged) {
1124 			//save
1125 			ResourceSaver::save(p_res->get_path(), p_res, flags);
1126 		}
1127 		processed[p_res] = false; //because it's a file
1128 		return false;
1129 	} else {
1130 
1131 		processed[p_res] = changed;
1132 		return changed;
1133 	}
1134 }
1135 
_find_and_save_edited_subresources(Object * obj,Map<RES,bool> & processed,int32_t flags)1136 bool EditorNode::_find_and_save_edited_subresources(Object *obj, Map<RES, bool> &processed, int32_t flags) {
1137 
1138 	bool ret_changed = false;
1139 	List<PropertyInfo> pi;
1140 	obj->get_property_list(&pi);
1141 	for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) {
1142 
1143 		if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
1144 			continue;
1145 
1146 		switch (E->get().type) {
1147 			case Variant::OBJECT: {
1148 
1149 				RES res = obj->get(E->get().name);
1150 
1151 				if (_find_and_save_resource(res, processed, flags))
1152 					ret_changed = true;
1153 
1154 			} break;
1155 			case Variant::ARRAY: {
1156 
1157 				Array varray = obj->get(E->get().name);
1158 				int len = varray.size();
1159 				for (int i = 0; i < len; i++) {
1160 
1161 					const Variant &v = varray.get(i);
1162 					RES res = v;
1163 					if (_find_and_save_resource(res, processed, flags))
1164 						ret_changed = true;
1165 				}
1166 
1167 			} break;
1168 			case Variant::DICTIONARY: {
1169 
1170 				Dictionary d = obj->get(E->get().name);
1171 				List<Variant> keys;
1172 				d.get_key_list(&keys);
1173 				for (List<Variant>::Element *F = keys.front(); F; F = F->next()) {
1174 
1175 					Variant v = d[F->get()];
1176 					RES res = v;
1177 					if (_find_and_save_resource(res, processed, flags))
1178 						ret_changed = true;
1179 				}
1180 			} break;
1181 			default: {
1182 			}
1183 		}
1184 	}
1185 
1186 	return ret_changed;
1187 }
1188 
_save_edited_subresources(Node * scene,Map<RES,bool> & processed,int32_t flags)1189 void EditorNode::_save_edited_subresources(Node *scene, Map<RES, bool> &processed, int32_t flags) {
1190 
1191 	_find_and_save_edited_subresources(scene, processed, flags);
1192 
1193 	for (int i = 0; i < scene->get_child_count(); i++) {
1194 
1195 		Node *n = scene->get_child(i);
1196 		if (n->get_owner() != editor_data.get_edited_scene_root())
1197 			continue;
1198 		_save_edited_subresources(n, processed, flags);
1199 	}
1200 }
1201 
_find_node_types(Node * p_node,int & count_2d,int & count_3d)1202 void EditorNode::_find_node_types(Node *p_node, int &count_2d, int &count_3d) {
1203 
1204 	if (p_node->is_class("Viewport") || (p_node != editor_data.get_edited_scene_root() && p_node->get_owner() != editor_data.get_edited_scene_root()))
1205 		return;
1206 
1207 	if (p_node->is_class("CanvasItem"))
1208 		count_2d++;
1209 	else if (p_node->is_class("Spatial"))
1210 		count_3d++;
1211 
1212 	for (int i = 0; i < p_node->get_child_count(); i++)
1213 		_find_node_types(p_node->get_child(i), count_2d, count_3d);
1214 }
1215 
_save_scene_with_preview(String p_file,int p_idx)1216 void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
1217 
1218 	EditorProgress save("save", TTR("Saving Scene"), 4);
1219 
1220 	if (editor_data.get_edited_scene_root() != NULL) {
1221 		save.step(TTR("Analyzing"), 0);
1222 
1223 		int c2d = 0;
1224 		int c3d = 0;
1225 
1226 		_find_node_types(editor_data.get_edited_scene_root(), c2d, c3d);
1227 
1228 		save.step(TTR("Creating Thumbnail"), 1);
1229 		//current view?
1230 
1231 		Ref<Image> img;
1232 		// If neither 3D or 2D nodes are present, make a 1x1 black texture.
1233 		// We cannot fallback on the 2D editor, because it may not have been used yet,
1234 		// which would result in an invalid texture.
1235 		if (c3d == 0 && c2d == 0) {
1236 			img.instance();
1237 			img->create(1, 1, 0, Image::FORMAT_RGB8);
1238 		} else if (c3d < c2d) {
1239 			Ref<ViewportTexture> viewport_texture = scene_root->get_texture();
1240 			if (viewport_texture->get_width() > 0 && viewport_texture->get_height() > 0) {
1241 				img = viewport_texture->get_data();
1242 			}
1243 		} else {
1244 			// The 3D editor may be disabled as a feature, but scenes can still be opened.
1245 			// This check prevents the preview from regenerating in case those scenes are then saved.
1246 			Ref<EditorFeatureProfile> profile = feature_profile_manager->get_current_profile();
1247 			if (profile.is_valid() && !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D)) {
1248 				img = SpatialEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_texture()->get_data();
1249 			}
1250 		}
1251 
1252 		if (img.is_valid() && img->get_width() > 0 && img->get_height() > 0) {
1253 			img = img->duplicate();
1254 
1255 			save.step(TTR("Creating Thumbnail"), 2);
1256 			save.step(TTR("Creating Thumbnail"), 3);
1257 
1258 			int preview_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
1259 			preview_size *= EDSCALE;
1260 
1261 			// consider a square region
1262 			int vp_size = MIN(img->get_width(), img->get_height());
1263 			int x = (img->get_width() - vp_size) / 2;
1264 			int y = (img->get_height() - vp_size) / 2;
1265 
1266 			if (vp_size < preview_size) {
1267 				// just square it.
1268 				img->crop_from_point(x, y, vp_size, vp_size);
1269 			} else {
1270 				int ratio = vp_size / preview_size;
1271 				int size = preview_size * MAX(1, ratio / 2);
1272 
1273 				x = (img->get_width() - size) / 2;
1274 				y = (img->get_height() - size) / 2;
1275 
1276 				img->crop_from_point(x, y, size, size);
1277 				img->resize(preview_size, preview_size, Image::INTERPOLATE_LANCZOS);
1278 			}
1279 			img->convert(Image::FORMAT_RGB8);
1280 
1281 			img->flip_y();
1282 
1283 			//save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5
1284 			String temp_path = EditorSettings::get_singleton()->get_cache_dir();
1285 			String cache_base = ProjectSettings::get_singleton()->globalize_path(p_file).md5_text();
1286 			cache_base = temp_path.plus_file("resthumb-" + cache_base);
1287 
1288 			//does not have it, try to load a cached thumbnail
1289 
1290 			String file = cache_base + ".png";
1291 
1292 			post_process_preview(img);
1293 			img->save_png(file);
1294 		}
1295 	}
1296 
1297 	save.step(TTR("Saving Scene"), 4);
1298 	_save_scene(p_file, p_idx);
1299 
1300 	if (!singleton->cmdline_export_mode) {
1301 		EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
1302 	}
1303 }
1304 
_validate_scene_recursive(const String & p_filename,Node * p_node)1305 bool EditorNode::_validate_scene_recursive(const String &p_filename, Node *p_node) {
1306 
1307 	for (int i = 0; i < p_node->get_child_count(); i++) {
1308 		Node *child = p_node->get_child(i);
1309 		if (child->get_filename() == p_filename) {
1310 			return true;
1311 		}
1312 
1313 		if (_validate_scene_recursive(p_filename, child)) {
1314 			return true;
1315 		}
1316 	}
1317 
1318 	return false;
1319 }
1320 
_find_edited_resources(const Ref<Resource> & p_resource,Set<Ref<Resource>> & edited_resources)1321 static bool _find_edited_resources(const Ref<Resource> &p_resource, Set<Ref<Resource> > &edited_resources) {
1322 
1323 	if (p_resource->is_edited()) {
1324 		edited_resources.insert(p_resource);
1325 		return true;
1326 	}
1327 
1328 	List<PropertyInfo> plist;
1329 
1330 	p_resource->get_property_list(&plist);
1331 
1332 	for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
1333 		if (E->get().type == Variant::OBJECT && E->get().usage & PROPERTY_USAGE_STORAGE && !(E->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT)) {
1334 			RES res = p_resource->get(E->get().name);
1335 			if (res.is_null()) {
1336 				continue;
1337 			}
1338 			if (res->get_path().is_resource_file()) { //not a subresource, continue
1339 				continue;
1340 			}
1341 			if (_find_edited_resources(res, edited_resources)) {
1342 				return true;
1343 			}
1344 		}
1345 	}
1346 
1347 	return false;
1348 }
1349 
_save_external_resources()1350 int EditorNode::_save_external_resources() {
1351 	//save external resources and its subresources if any was modified
1352 
1353 	int flg = 0;
1354 	if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources"))
1355 		flg |= ResourceSaver::FLAG_COMPRESS;
1356 	flg |= ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
1357 
1358 	Set<Ref<Resource> > edited_subresources;
1359 	int saved = 0;
1360 	List<Ref<Resource> > cached;
1361 	ResourceCache::get_cached_resources(&cached);
1362 	for (List<Ref<Resource> >::Element *E = cached.front(); E; E = E->next()) {
1363 
1364 		Ref<Resource> res = E->get();
1365 		if (!res->get_path().is_resource_file())
1366 			continue;
1367 		//not only check if this resourec is edited, check contained subresources too
1368 		if (_find_edited_resources(res, edited_subresources)) {
1369 			ResourceSaver::save(res->get_path(), res, flg);
1370 			saved++;
1371 		}
1372 	}
1373 
1374 	// clear later, because user may have put the same subresource in two different resources,
1375 	// which will be shared until the next reload
1376 
1377 	for (Set<Ref<Resource> >::Element *E = edited_subresources.front(); E; E = E->next()) {
1378 		Ref<Resource> res = E->get();
1379 		res->set_edited(false);
1380 	}
1381 
1382 	return saved;
1383 }
1384 
_save_scene(String p_file,int idx)1385 void EditorNode::_save_scene(String p_file, int idx) {
1386 
1387 	Node *scene = editor_data.get_edited_scene_root(idx);
1388 
1389 	if (!scene) {
1390 
1391 		show_accept(TTR("This operation can't be done without a tree root."), TTR("OK"));
1392 		return;
1393 	}
1394 
1395 	if (scene->get_filename() != String() && _validate_scene_recursive(scene->get_filename(), scene)) {
1396 		show_accept(TTR("This scene can't be saved because there is a cyclic instancing inclusion.\nPlease resolve it and then attempt to save again."), TTR("OK"));
1397 		return;
1398 	}
1399 
1400 	editor_data.apply_changes_in_editors();
1401 	_save_default_environment();
1402 
1403 	_set_scene_metadata(p_file, idx);
1404 
1405 	Ref<PackedScene> sdata;
1406 
1407 	if (ResourceCache::has(p_file)) {
1408 		// something may be referencing this resource and we are good with that.
1409 		// we must update it, but also let the previous scene state go, as
1410 		// old version still work for referencing changes in instanced or inherited scenes
1411 
1412 		sdata = Ref<PackedScene>(Object::cast_to<PackedScene>(ResourceCache::get(p_file)));
1413 		if (sdata.is_valid())
1414 			sdata->recreate_state();
1415 		else
1416 			sdata.instance();
1417 	} else {
1418 		sdata.instance();
1419 	}
1420 	Error err = sdata->pack(scene);
1421 
1422 	if (err != OK) {
1423 
1424 		show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("OK"));
1425 		return;
1426 	}
1427 
1428 	// force creation of node path cache
1429 	// (hacky but needed for the tree to update properly)
1430 	Node *dummy_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
1431 	if (!dummy_scene) {
1432 		show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("OK"));
1433 		return;
1434 	}
1435 	memdelete(dummy_scene);
1436 
1437 	int flg = 0;
1438 	if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources"))
1439 		flg |= ResourceSaver::FLAG_COMPRESS;
1440 	flg |= ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
1441 
1442 	err = ResourceSaver::save(p_file, sdata, flg);
1443 
1444 	_save_external_resources();
1445 
1446 	editor_data.save_editor_external_data();
1447 	if (err == OK) {
1448 		scene->set_filename(ProjectSettings::get_singleton()->localize_path(p_file));
1449 		if (idx < 0 || idx == editor_data.get_edited_scene())
1450 			set_current_version(editor_data.get_undo_redo().get_version());
1451 		else
1452 			editor_data.set_edited_scene_version(0, idx);
1453 
1454 		editor_folding.save_scene_folding(scene, p_file);
1455 
1456 		_update_title();
1457 		_update_scene_tabs();
1458 	} else {
1459 
1460 		_dialog_display_save_error(p_file, err);
1461 	}
1462 }
1463 
save_all_scenes()1464 void EditorNode::save_all_scenes() {
1465 
1466 	_menu_option_confirm(RUN_STOP, true);
1467 	_save_all_scenes();
1468 }
1469 
save_scene_list(Vector<String> p_scene_filenames)1470 void EditorNode::save_scene_list(Vector<String> p_scene_filenames) {
1471 
1472 	for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
1473 		Node *scene = editor_data.get_edited_scene_root(i);
1474 
1475 		if (scene && (p_scene_filenames.find(scene->get_filename()) >= 0)) {
1476 			_save_scene(scene->get_filename(), i);
1477 		}
1478 	}
1479 }
1480 
restart_editor()1481 void EditorNode::restart_editor() {
1482 
1483 	exiting = true;
1484 
1485 	String to_reopen;
1486 	if (get_tree()->get_edited_scene_root()) {
1487 		to_reopen = get_tree()->get_edited_scene_root()->get_filename();
1488 	}
1489 
1490 	_exit_editor();
1491 
1492 	List<String> args;
1493 	args.push_back("--path");
1494 	args.push_back(ProjectSettings::get_singleton()->get_resource_path());
1495 	args.push_back("-e");
1496 	if (to_reopen != String()) {
1497 		args.push_back(to_reopen);
1498 	}
1499 
1500 	OS::get_singleton()->set_restart_on_exit(true, args);
1501 }
1502 
_save_all_scenes()1503 void EditorNode::_save_all_scenes() {
1504 
1505 	for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
1506 		Node *scene = editor_data.get_edited_scene_root(i);
1507 		if (scene && scene->get_filename() != "") {
1508 			if (i != editor_data.get_edited_scene())
1509 				_save_scene(scene->get_filename(), i);
1510 			else
1511 				_save_scene_with_preview(scene->get_filename());
1512 		} // else: ignore new scenes
1513 	}
1514 
1515 	_save_default_environment();
1516 }
1517 
_mark_unsaved_scenes()1518 void EditorNode::_mark_unsaved_scenes() {
1519 
1520 	for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
1521 
1522 		Node *node = editor_data.get_edited_scene_root(i);
1523 		if (!node)
1524 			continue;
1525 
1526 		String path = node->get_filename();
1527 		if (!(path == String() || FileAccess::exists(path))) {
1528 
1529 			if (i == editor_data.get_edited_scene())
1530 				set_current_version(-1);
1531 			else
1532 				editor_data.set_edited_scene_version(-1, i);
1533 		}
1534 	}
1535 
1536 	_update_title();
1537 	_update_scene_tabs();
1538 }
1539 
_dialog_action(String p_file)1540 void EditorNode::_dialog_action(String p_file) {
1541 
1542 	switch (current_option) {
1543 		case FILE_NEW_INHERITED_SCENE: {
1544 
1545 			Node *scene = editor_data.get_edited_scene_root();
1546 			// If the previous scene is rootless, just close it in favor of the new one.
1547 			if (!scene)
1548 				_menu_option_confirm(FILE_CLOSE, true);
1549 
1550 			load_scene(p_file, false, true);
1551 		} break;
1552 		case FILE_OPEN_SCENE: {
1553 
1554 			load_scene(p_file);
1555 		} break;
1556 		case SETTINGS_PICK_MAIN_SCENE: {
1557 
1558 			ProjectSettings::get_singleton()->set("application/run/main_scene", p_file);
1559 			ProjectSettings::get_singleton()->save();
1560 			//would be nice to show the project manager opened with the highlighted field..
1561 
1562 			if (pick_main_scene->has_meta("from_native") && (bool)pick_main_scene->get_meta("from_native")) {
1563 				run_native->resume_run_native();
1564 			} else {
1565 				_run(false, ""); // automatically run the project
1566 			}
1567 		} break;
1568 		case FILE_CLOSE:
1569 		case FILE_CLOSE_ALL_AND_QUIT:
1570 		case FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER:
1571 		case SCENE_TAB_CLOSE:
1572 		case FILE_SAVE_SCENE:
1573 		case FILE_SAVE_AS_SCENE: {
1574 
1575 			int scene_idx = (current_option == FILE_SAVE_SCENE || current_option == FILE_SAVE_AS_SCENE) ? -1 : tab_closing;
1576 
1577 			if (file->get_mode() == EditorFileDialog::MODE_SAVE_FILE) {
1578 				bool same_open_scene = false;
1579 				for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
1580 					if (editor_data.get_scene_path(i) == p_file && i != scene_idx)
1581 						same_open_scene = true;
1582 				}
1583 
1584 				if (same_open_scene) {
1585 					show_warning(TTR("Can't overwrite scene that is still open!"));
1586 					return;
1587 				}
1588 
1589 				_save_default_environment();
1590 				_save_scene_with_preview(p_file, scene_idx);
1591 				_add_to_recent_scenes(p_file);
1592 				save_layout();
1593 
1594 				if (scene_idx != -1)
1595 					_discard_changes();
1596 			}
1597 
1598 		} break;
1599 
1600 		case FILE_SAVE_AND_RUN: {
1601 			if (file->get_mode() == EditorFileDialog::MODE_SAVE_FILE) {
1602 
1603 				_save_default_environment();
1604 				_save_scene_with_preview(p_file);
1605 				_run(false, p_file);
1606 			}
1607 		} break;
1608 
1609 		case FILE_EXPORT_MESH_LIBRARY: {
1610 
1611 			Ref<MeshLibrary> ml;
1612 			if (file_export_lib_merge->is_pressed() && FileAccess::exists(p_file)) {
1613 				ml = ResourceLoader::load(p_file, "MeshLibrary");
1614 
1615 				if (ml.is_null()) {
1616 					show_accept(TTR("Can't load MeshLibrary for merging!"), TTR("OK"));
1617 					return;
1618 				}
1619 			}
1620 
1621 			if (ml.is_null()) {
1622 				ml = Ref<MeshLibrary>(memnew(MeshLibrary));
1623 			}
1624 
1625 			MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(), ml, true);
1626 
1627 			Error err = ResourceSaver::save(p_file, ml);
1628 			if (err) {
1629 				show_accept(TTR("Error saving MeshLibrary!"), TTR("OK"));
1630 				return;
1631 			}
1632 
1633 		} break;
1634 		case FILE_EXPORT_TILESET: {
1635 
1636 			Ref<TileSet> tileset;
1637 			if (FileAccess::exists(p_file) && file_export_lib_merge->is_pressed()) {
1638 				tileset = ResourceLoader::load(p_file, "TileSet");
1639 
1640 				if (tileset.is_null()) {
1641 					show_accept(TTR("Can't load TileSet for merging!"), TTR("OK"));
1642 					return;
1643 				}
1644 
1645 			} else {
1646 				tileset = Ref<TileSet>(memnew(TileSet));
1647 			}
1648 
1649 			TileSetEditor::update_library_file(editor_data.get_edited_scene_root(), tileset, true);
1650 
1651 			Error err = ResourceSaver::save(p_file, tileset);
1652 			if (err) {
1653 
1654 				show_accept(TTR("Error saving TileSet!"), TTR("OK"));
1655 				return;
1656 			}
1657 		} break;
1658 
1659 		case RESOURCE_SAVE:
1660 		case RESOURCE_SAVE_AS: {
1661 
1662 			ERR_FAIL_COND(saving_resource.is_null());
1663 			save_resource_in_path(saving_resource, p_file);
1664 			saving_resource = Ref<Resource>();
1665 			ObjectID current = editor_history.get_current();
1666 			Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
1667 			ERR_FAIL_COND(!current_obj);
1668 			current_obj->_change_notify();
1669 		} break;
1670 		case SETTINGS_LAYOUT_SAVE: {
1671 
1672 			if (p_file.empty())
1673 				return;
1674 
1675 			Ref<ConfigFile> config;
1676 			config.instance();
1677 			Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
1678 
1679 			if (err == ERR_FILE_CANT_OPEN || err == ERR_FILE_NOT_FOUND) {
1680 				config.instance(); // new config
1681 			} else if (err != OK) {
1682 				show_warning(TTR("Error trying to save layout!"));
1683 				return;
1684 			}
1685 
1686 			_save_docks_to_config(config, p_file);
1687 
1688 			config->save(EditorSettings::get_singleton()->get_editor_layouts_config());
1689 
1690 			layout_dialog->hide();
1691 			_update_layouts_menu();
1692 
1693 			if (p_file == "Default") {
1694 				show_warning(TTR("Default editor layout overridden."));
1695 			}
1696 
1697 		} break;
1698 		case SETTINGS_LAYOUT_DELETE: {
1699 
1700 			if (p_file.empty())
1701 				return;
1702 
1703 			Ref<ConfigFile> config;
1704 			config.instance();
1705 			Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
1706 
1707 			if (err != OK || !config->has_section(p_file)) {
1708 				show_warning(TTR("Layout name not found!"));
1709 				return;
1710 			}
1711 
1712 			// erase
1713 			List<String> keys;
1714 			config->get_section_keys(p_file, &keys);
1715 			for (List<String>::Element *E = keys.front(); E; E = E->next()) {
1716 				config->set_value(p_file, E->get(), Variant());
1717 			}
1718 
1719 			config->save(EditorSettings::get_singleton()->get_editor_layouts_config());
1720 
1721 			layout_dialog->hide();
1722 			_update_layouts_menu();
1723 
1724 			if (p_file == "Default") {
1725 				show_warning(TTR("Restored default layout to base settings."));
1726 			}
1727 
1728 		} break;
1729 		default: { //save scene?
1730 
1731 			if (file->get_mode() == EditorFileDialog::MODE_SAVE_FILE) {
1732 				_save_scene_with_preview(p_file);
1733 			}
1734 
1735 		} break;
1736 	}
1737 }
1738 
item_has_editor(Object * p_object)1739 bool EditorNode::item_has_editor(Object *p_object) {
1740 
1741 	if (_is_class_editor_disabled_by_feature_profile(p_object->get_class())) {
1742 		return false;
1743 	}
1744 
1745 	return editor_data.get_subeditors(p_object).size() > 0;
1746 }
1747 
edit_item_resource(RES p_resource)1748 void EditorNode::edit_item_resource(RES p_resource) {
1749 	edit_item(p_resource.ptr());
1750 }
1751 
_is_class_editor_disabled_by_feature_profile(const StringName & p_class)1752 bool EditorNode::_is_class_editor_disabled_by_feature_profile(const StringName &p_class) {
1753 
1754 	Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();
1755 	if (profile.is_null()) {
1756 		return false;
1757 	}
1758 
1759 	StringName class_name = p_class;
1760 
1761 	while (class_name != StringName()) {
1762 
1763 		if (profile->is_class_disabled(class_name)) {
1764 			return true;
1765 		}
1766 		if (profile->is_class_editor_disabled(class_name)) {
1767 			return true;
1768 		}
1769 		class_name = ClassDB::get_parent_class(class_name);
1770 	}
1771 
1772 	return false;
1773 }
1774 
edit_item(Object * p_object)1775 void EditorNode::edit_item(Object *p_object) {
1776 
1777 	Vector<EditorPlugin *> sub_plugins;
1778 
1779 	if (p_object) {
1780 		if (_is_class_editor_disabled_by_feature_profile(p_object->get_class())) {
1781 			return;
1782 		}
1783 		sub_plugins = editor_data.get_subeditors(p_object);
1784 	}
1785 
1786 	if (!sub_plugins.empty()) {
1787 
1788 		bool same = true;
1789 		if (sub_plugins.size() == editor_plugins_over->get_plugins_list().size()) {
1790 			for (int i = 0; i < sub_plugins.size(); i++) {
1791 				if (sub_plugins[i] != editor_plugins_over->get_plugins_list()[i]) {
1792 					same = false;
1793 				}
1794 			}
1795 		} else {
1796 			same = false;
1797 		}
1798 		if (!same) {
1799 			_display_top_editors(false);
1800 			_set_top_editors(sub_plugins);
1801 		}
1802 		_set_editing_top_editors(p_object);
1803 		_display_top_editors(true);
1804 	} else {
1805 		hide_top_editors();
1806 	}
1807 }
1808 
push_item(Object * p_object,const String & p_property,bool p_inspector_only)1809 void EditorNode::push_item(Object *p_object, const String &p_property, bool p_inspector_only) {
1810 
1811 	if (!p_object) {
1812 		get_inspector()->edit(NULL);
1813 		node_dock->set_node(NULL);
1814 		scene_tree_dock->set_selected(NULL);
1815 		inspector_dock->update(NULL);
1816 		return;
1817 	}
1818 
1819 	uint32_t id = p_object->get_instance_id();
1820 	if (id != editor_history.get_current()) {
1821 
1822 		if (p_inspector_only) {
1823 			editor_history.add_object_inspector_only(id);
1824 		} else if (p_property == "")
1825 			editor_history.add_object(id);
1826 		else
1827 			editor_history.add_object(id, p_property);
1828 	}
1829 
1830 	_edit_current();
1831 }
1832 
_save_default_environment()1833 void EditorNode::_save_default_environment() {
1834 
1835 	Ref<Environment> fallback = get_tree()->get_root()->get_world()->get_fallback_environment();
1836 
1837 	if (fallback.is_valid() && fallback->get_path().is_resource_file()) {
1838 		Map<RES, bool> processed;
1839 		_find_and_save_edited_subresources(fallback.ptr(), processed, 0);
1840 		save_resource_in_path(fallback, fallback->get_path());
1841 	}
1842 }
1843 
hide_top_editors()1844 void EditorNode::hide_top_editors() {
1845 
1846 	_display_top_editors(false);
1847 
1848 	editor_plugins_over->clear();
1849 }
1850 
_display_top_editors(bool p_display)1851 void EditorNode::_display_top_editors(bool p_display) {
1852 	editor_plugins_over->make_visible(p_display);
1853 }
1854 
_set_top_editors(Vector<EditorPlugin * > p_editor_plugins_over)1855 void EditorNode::_set_top_editors(Vector<EditorPlugin *> p_editor_plugins_over) {
1856 	editor_plugins_over->set_plugins_list(p_editor_plugins_over);
1857 }
1858 
_set_editing_top_editors(Object * p_current_object)1859 void EditorNode::_set_editing_top_editors(Object *p_current_object) {
1860 	editor_plugins_over->edit(p_current_object);
1861 }
1862 
overrides_external_editor(Object * p_object)1863 static bool overrides_external_editor(Object *p_object) {
1864 
1865 	Script *script = Object::cast_to<Script>(p_object);
1866 
1867 	if (!script)
1868 		return false;
1869 
1870 	return script->get_language()->overrides_external_editor();
1871 }
1872 
_edit_current()1873 void EditorNode::_edit_current() {
1874 
1875 	uint32_t current = editor_history.get_current();
1876 	Object *current_obj = current > 0 ? ObjectDB::get_instance(current) : NULL;
1877 	bool inspector_only = editor_history.is_current_inspector_only();
1878 
1879 	this->current = current_obj;
1880 
1881 	if (!current_obj) {
1882 
1883 		scene_tree_dock->set_selected(NULL);
1884 		get_inspector()->edit(NULL);
1885 		node_dock->set_node(NULL);
1886 		inspector_dock->update(NULL);
1887 
1888 		_display_top_editors(false);
1889 
1890 		return;
1891 	}
1892 
1893 	Object *prev_inspected_object = get_inspector()->get_edited_object();
1894 
1895 	bool capitalize = bool(EDITOR_GET("interface/inspector/capitalize_properties"));
1896 	bool disable_folding = bool(EDITOR_GET("interface/inspector/disable_folding"));
1897 	bool is_resource = current_obj->is_class("Resource");
1898 	bool is_node = current_obj->is_class("Node");
1899 
1900 	String editable_warning; //none by default
1901 
1902 	if (is_resource) {
1903 
1904 		Resource *current_res = Object::cast_to<Resource>(current_obj);
1905 		ERR_FAIL_COND(!current_res);
1906 		get_inspector()->edit(current_res);
1907 		scene_tree_dock->set_selected(NULL);
1908 		node_dock->set_node(NULL);
1909 		inspector_dock->update(NULL);
1910 		EditorNode::get_singleton()->get_import_dock()->set_edit_path(current_res->get_path());
1911 
1912 		int subr_idx = current_res->get_path().find("::");
1913 		if (subr_idx != -1) {
1914 			String base_path = current_res->get_path().substr(0, subr_idx);
1915 			if (FileAccess::exists(base_path + ".import")) {
1916 				editable_warning = TTR("This resource belongs to a scene that was imported, so it's not editable.\nPlease read the documentation relevant to importing scenes to better understand this workflow.");
1917 			} else {
1918 				if ((!get_edited_scene() || get_edited_scene()->get_filename() != base_path) && ResourceLoader::get_resource_type(base_path) == "PackedScene") {
1919 					editable_warning = TTR("This resource belongs to a scene that was instanced or inherited.\nChanges to it won't be kept when saving the current scene.");
1920 				}
1921 			}
1922 		} else if (current_res->get_path().is_resource_file()) {
1923 			if (FileAccess::exists(current_res->get_path() + ".import")) {
1924 				editable_warning = TTR("This resource was imported, so it's not editable. Change its settings in the import panel and then re-import.");
1925 			}
1926 		}
1927 	} else if (is_node) {
1928 
1929 		Node *current_node = Object::cast_to<Node>(current_obj);
1930 		ERR_FAIL_COND(!current_node);
1931 
1932 		get_inspector()->edit(current_node);
1933 		if (current_node->is_inside_tree()) {
1934 			node_dock->set_node(current_node);
1935 			scene_tree_dock->set_selected(current_node);
1936 			inspector_dock->update(current_node);
1937 		} else {
1938 			node_dock->set_node(NULL);
1939 			scene_tree_dock->set_selected(NULL);
1940 			inspector_dock->update(NULL);
1941 		}
1942 
1943 		if (get_edited_scene() && get_edited_scene()->get_filename() != String()) {
1944 			String source_scene = get_edited_scene()->get_filename();
1945 			if (FileAccess::exists(source_scene + ".import")) {
1946 				editable_warning = TTR("This scene was imported, so changes to it won't be kept.\nInstancing it or inheriting will allow making changes to it.\nPlease read the documentation relevant to importing scenes to better understand this workflow.");
1947 			}
1948 		}
1949 
1950 	} else {
1951 
1952 		Node *selected_node = NULL;
1953 
1954 		if (current_obj->is_class("ScriptEditorDebuggerInspectedObject")) {
1955 			editable_warning = TTR("This is a remote object, so changes to it won't be kept.\nPlease read the documentation relevant to debugging to better understand this workflow.");
1956 			capitalize = false;
1957 			disable_folding = true;
1958 		} else if (current_obj->is_class("MultiNodeEdit")) {
1959 			Node *scene = get_edited_scene();
1960 			if (scene) {
1961 				MultiNodeEdit *multi_node_edit = Object::cast_to<MultiNodeEdit>(current_obj);
1962 				int node_count = multi_node_edit->get_node_count();
1963 				if (node_count > 0) {
1964 					List<Node *> multi_nodes;
1965 					for (int node_index = 0; node_index < node_count; ++node_index) {
1966 						Node *node = scene->get_node(multi_node_edit->get_node(node_index));
1967 						if (node) {
1968 							multi_nodes.push_back(node);
1969 						}
1970 					}
1971 					if (!multi_nodes.empty()) {
1972 						// Pick the top-most node
1973 						multi_nodes.sort_custom<Node::Comparator>();
1974 						selected_node = multi_nodes.front()->get();
1975 					}
1976 				}
1977 			}
1978 		}
1979 
1980 		get_inspector()->edit(current_obj);
1981 		node_dock->set_node(NULL);
1982 		scene_tree_dock->set_selected(selected_node);
1983 		inspector_dock->update(NULL);
1984 	}
1985 
1986 	if (current_obj == prev_inspected_object) {
1987 		// Make sure inspected properties are restored.
1988 		get_inspector()->update_tree();
1989 	}
1990 
1991 	inspector_dock->set_warning(editable_warning);
1992 
1993 	if (get_inspector()->is_capitalize_paths_enabled() != capitalize) {
1994 		get_inspector()->set_enable_capitalize_paths(capitalize);
1995 	}
1996 
1997 	if (get_inspector()->is_using_folding() == disable_folding) {
1998 		get_inspector()->set_use_folding(!disable_folding);
1999 	}
2000 
2001 	/* Take care of PLUGIN EDITOR */
2002 
2003 	if (!inspector_only) {
2004 
2005 		EditorPlugin *main_plugin = editor_data.get_editor(current_obj);
2006 
2007 		for (int i = 0; i < editor_table.size(); i++) {
2008 			if (editor_table[i] == main_plugin && !main_editor_buttons[i]->is_visible()) {
2009 				main_plugin = NULL; //if button is not visible, then no plugin active
2010 			}
2011 		}
2012 
2013 		if (main_plugin) {
2014 
2015 			// special case if use of external editor is true
2016 			if (main_plugin->get_name() == "Script" && current_obj->get_class_name() != StringName("VisualScript") && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) {
2017 				if (!changing_scene)
2018 					main_plugin->edit(current_obj);
2019 			}
2020 
2021 			else if (main_plugin != editor_plugin_screen && (!ScriptEditor::get_singleton() || !ScriptEditor::get_singleton()->is_visible_in_tree() || ScriptEditor::get_singleton()->can_take_away_focus())) {
2022 				// update screen main_plugin
2023 
2024 				if (!changing_scene) {
2025 
2026 					if (editor_plugin_screen)
2027 						editor_plugin_screen->make_visible(false);
2028 					editor_plugin_screen = main_plugin;
2029 					editor_plugin_screen->edit(current_obj);
2030 
2031 					editor_plugin_screen->make_visible(true);
2032 
2033 					int plugin_count = editor_data.get_editor_plugin_count();
2034 					for (int i = 0; i < plugin_count; i++) {
2035 						editor_data.get_editor_plugin(i)->notify_main_screen_changed(editor_plugin_screen->get_name());
2036 					}
2037 
2038 					for (int i = 0; i < editor_table.size(); i++) {
2039 
2040 						main_editor_buttons[i]->set_pressed(editor_table[i] == main_plugin);
2041 					}
2042 				}
2043 
2044 			} else {
2045 
2046 				editor_plugin_screen->edit(current_obj);
2047 			}
2048 		}
2049 
2050 		Vector<EditorPlugin *> sub_plugins;
2051 
2052 		if (!_is_class_editor_disabled_by_feature_profile(current_obj->get_class())) {
2053 			sub_plugins = editor_data.get_subeditors(current_obj);
2054 		}
2055 
2056 		if (!sub_plugins.empty()) {
2057 			_display_top_editors(false);
2058 
2059 			_set_top_editors(sub_plugins);
2060 			_set_editing_top_editors(current_obj);
2061 			_display_top_editors(true);
2062 		} else if (!editor_plugins_over->get_plugins_list().empty()) {
2063 
2064 			hide_top_editors();
2065 		}
2066 	}
2067 
2068 	inspector_dock->update(current_obj);
2069 	inspector_dock->update_keying();
2070 }
2071 
_run(bool p_current,const String & p_custom)2072 void EditorNode::_run(bool p_current, const String &p_custom) {
2073 
2074 	if (editor_run.get_status() == EditorRun::STATUS_PLAY) {
2075 		play_button->set_pressed(!_playing_edited);
2076 		play_scene_button->set_pressed(_playing_edited);
2077 		return;
2078 	}
2079 
2080 	play_button->set_pressed(false);
2081 	play_button->set_icon(gui_base->get_icon("MainPlay", "EditorIcons"));
2082 	play_scene_button->set_pressed(false);
2083 	play_scene_button->set_icon(gui_base->get_icon("PlayScene", "EditorIcons"));
2084 	play_custom_scene_button->set_pressed(false);
2085 	play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons"));
2086 
2087 	String run_filename;
2088 	String args;
2089 	bool skip_breakpoints;
2090 
2091 	if (p_current || (editor_data.get_edited_scene_root() && p_custom != String() && p_custom == editor_data.get_edited_scene_root()->get_filename())) {
2092 		Node *scene = editor_data.get_edited_scene_root();
2093 
2094 		if (!scene) {
2095 			show_accept(TTR("There is no defined scene to run."), TTR("OK"));
2096 			return;
2097 		}
2098 
2099 		if (scene->get_filename() == "") {
2100 			current_option = -1;
2101 			_menu_option_confirm(FILE_SAVE_BEFORE_RUN, false);
2102 			return;
2103 		}
2104 
2105 		run_filename = scene->get_filename();
2106 	} else if (p_custom != "") {
2107 		run_filename = p_custom;
2108 	}
2109 
2110 	if (run_filename == "") {
2111 
2112 		//evidently, run the scene
2113 		if (!ensure_main_scene(false)) {
2114 			return;
2115 		}
2116 	}
2117 
2118 	if (bool(EDITOR_GET("run/auto_save/save_before_running"))) {
2119 
2120 		if (unsaved_cache) {
2121 
2122 			Node *scene = editor_data.get_edited_scene_root();
2123 
2124 			if (scene && scene->get_filename() != "") { // Only autosave if there is a scene and if it has a path.
2125 				_save_scene_with_preview(scene->get_filename());
2126 			}
2127 		}
2128 		_menu_option(FILE_SAVE_ALL_SCENES);
2129 		editor_data.save_editor_external_data();
2130 	}
2131 
2132 	if (!call_build())
2133 		return;
2134 
2135 	if (bool(EDITOR_GET("run/output/always_clear_output_on_play"))) {
2136 		log->clear();
2137 	}
2138 
2139 	if (bool(EDITOR_GET("run/output/always_open_output_on_play"))) {
2140 		make_bottom_panel_item_visible(log);
2141 	}
2142 
2143 	List<String> breakpoints;
2144 	editor_data.get_editor_breakpoints(&breakpoints);
2145 
2146 	args = ProjectSettings::get_singleton()->get("editor/main_run_args");
2147 	skip_breakpoints = ScriptEditor::get_singleton()->get_debugger()->is_skip_breakpoints();
2148 
2149 	Error error = editor_run.run(run_filename, args, breakpoints, skip_breakpoints);
2150 
2151 	if (error != OK) {
2152 
2153 		show_accept(TTR("Could not start subprocess!"), TTR("OK"));
2154 		return;
2155 	}
2156 
2157 	emit_signal("play_pressed");
2158 	if (p_current) {
2159 		play_scene_button->set_pressed(true);
2160 		play_scene_button->set_icon(gui_base->get_icon("Reload", "EditorIcons"));
2161 	} else if (p_custom != "") {
2162 		run_custom_filename = p_custom;
2163 		play_custom_scene_button->set_pressed(true);
2164 		play_custom_scene_button->set_icon(gui_base->get_icon("Reload", "EditorIcons"));
2165 	} else {
2166 		play_button->set_pressed(true);
2167 		play_button->set_icon(gui_base->get_icon("Reload", "EditorIcons"));
2168 	}
2169 	stop_button->set_disabled(false);
2170 
2171 	_playing_edited = p_current;
2172 }
2173 
_menu_option_confirm(int p_option,bool p_confirmed)2174 void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
2175 
2176 	if (!p_confirmed) //this may be a hack..
2177 		current_option = (MenuOptions)p_option;
2178 
2179 	switch (p_option) {
2180 		case FILE_NEW_SCENE: {
2181 
2182 			new_scene();
2183 
2184 		} break;
2185 		case FILE_NEW_INHERITED_SCENE:
2186 		case FILE_OPEN_SCENE: {
2187 
2188 			file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
2189 			List<String> extensions;
2190 			ResourceLoader::get_recognized_extensions_for_type("PackedScene", &extensions);
2191 			file->clear_filters();
2192 			for (int i = 0; i < extensions.size(); i++) {
2193 
2194 				file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
2195 			}
2196 
2197 			Node *scene = editor_data.get_edited_scene_root();
2198 			if (scene) {
2199 				file->set_current_path(scene->get_filename());
2200 			};
2201 			file->set_title(p_option == FILE_OPEN_SCENE ? TTR("Open Scene") : TTR("Open Base Scene"));
2202 			file->popup_centered_ratio();
2203 
2204 		} break;
2205 		case FILE_QUICK_OPEN: {
2206 
2207 			quick_open->popup_dialog("Resource", true);
2208 			quick_open->set_title(TTR("Quick Open..."));
2209 
2210 		} break;
2211 		case FILE_QUICK_OPEN_SCENE: {
2212 
2213 			quick_open->popup_dialog("PackedScene", true);
2214 			quick_open->set_title(TTR("Quick Open Scene..."));
2215 
2216 		} break;
2217 		case FILE_QUICK_OPEN_SCRIPT: {
2218 
2219 			quick_open->popup_dialog("Script", true);
2220 			quick_open->set_title(TTR("Quick Open Script..."));
2221 
2222 		} break;
2223 		case FILE_OPEN_PREV: {
2224 
2225 			if (previous_scenes.empty())
2226 				break;
2227 			opening_prev = true;
2228 			open_request(previous_scenes.back()->get());
2229 			previous_scenes.pop_back();
2230 
2231 		} break;
2232 		case FILE_CLOSE_OTHERS:
2233 		case FILE_CLOSE_RIGHT:
2234 		case FILE_CLOSE_ALL: {
2235 			if (editor_data.get_edited_scene_count() > 1 && (current_option != FILE_CLOSE_RIGHT || editor_data.get_edited_scene() < editor_data.get_edited_scene_count() - 1)) {
2236 				int next_tab = editor_data.get_edited_scene() + 1;
2237 				next_tab %= editor_data.get_edited_scene_count();
2238 				_scene_tab_closed(next_tab, current_option);
2239 			} else {
2240 				if (current_option != FILE_CLOSE_ALL)
2241 					current_option = -1;
2242 				else
2243 					_scene_tab_closed(editor_data.get_edited_scene());
2244 			}
2245 
2246 			if (p_confirmed)
2247 				_menu_option_confirm(SCENE_TAB_CLOSE, true);
2248 
2249 		} break;
2250 		case FILE_CLOSE_ALL_AND_QUIT:
2251 		case FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER:
2252 		case FILE_CLOSE: {
2253 
2254 			if (!p_confirmed) {
2255 				tab_closing = p_option == FILE_CLOSE ? editor_data.get_edited_scene() : _next_unsaved_scene(false);
2256 
2257 				if (unsaved_cache || p_option == FILE_CLOSE_ALL_AND_QUIT || p_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER) {
2258 					String scene_filename = editor_data.get_edited_scene_root(tab_closing)->get_filename();
2259 					save_confirmation->get_ok()->set_text(TTR("Save & Close"));
2260 					save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene_filename != "" ? scene_filename : "unsaved scene"));
2261 					save_confirmation->popup_centered_minsize();
2262 					break;
2263 				}
2264 			} else if (p_option == FILE_CLOSE) {
2265 				tab_closing = editor_data.get_edited_scene();
2266 			}
2267 			if (!editor_data.get_edited_scene_root(tab_closing)) {
2268 				// empty tab
2269 				_scene_tab_closed(tab_closing);
2270 				break;
2271 			}
2272 
2273 			FALLTHROUGH;
2274 		}
2275 		case SCENE_TAB_CLOSE:
2276 		case FILE_SAVE_SCENE: {
2277 
2278 			int scene_idx = (p_option == FILE_SAVE_SCENE) ? -1 : tab_closing;
2279 
2280 			Node *scene = editor_data.get_edited_scene_root(scene_idx);
2281 			if (scene && scene->get_filename() != "") {
2282 
2283 				if (scene_idx != editor_data.get_edited_scene())
2284 					_save_scene_with_preview(scene->get_filename(), scene_idx);
2285 				else
2286 					_save_scene_with_preview(scene->get_filename());
2287 
2288 				if (scene_idx != -1)
2289 					_discard_changes();
2290 				save_layout();
2291 
2292 				break;
2293 			}
2294 			FALLTHROUGH;
2295 		}
2296 		case FILE_SAVE_AS_SCENE: {
2297 			int scene_idx = (p_option == FILE_SAVE_SCENE || p_option == FILE_SAVE_AS_SCENE) ? -1 : tab_closing;
2298 
2299 			Node *scene = editor_data.get_edited_scene_root(scene_idx);
2300 
2301 			if (!scene) {
2302 
2303 				int saved = _save_external_resources();
2304 				String err_text;
2305 				if (saved > 0) {
2306 					err_text = vformat(TTR("Saved %s modified resource(s)."), itos(saved));
2307 				} else {
2308 					err_text = TTR("A root node is required to save the scene.");
2309 				}
2310 
2311 				show_accept(err_text, TTR("OK"));
2312 				break;
2313 			}
2314 
2315 			file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
2316 
2317 			List<String> extensions;
2318 			Ref<PackedScene> sd = memnew(PackedScene);
2319 			ResourceSaver::get_recognized_extensions(sd, &extensions);
2320 			file->clear_filters();
2321 			for (int i = 0; i < extensions.size(); i++) {
2322 
2323 				file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
2324 			}
2325 
2326 			if (scene->get_filename() != "") {
2327 				file->set_current_path(scene->get_filename());
2328 				if (extensions.size()) {
2329 					String ext = scene->get_filename().get_extension().to_lower();
2330 					if (extensions.find(ext) == NULL) {
2331 						file->set_current_path(scene->get_filename().replacen("." + ext, "." + extensions.front()->get()));
2332 					}
2333 				}
2334 			} else {
2335 
2336 				String existing;
2337 				if (extensions.size()) {
2338 					String root_name(scene->get_name());
2339 					existing = root_name + "." + extensions.front()->get().to_lower();
2340 				}
2341 				file->set_current_path(existing);
2342 			}
2343 			file->popup_centered_ratio();
2344 			file->set_title(TTR("Save Scene As..."));
2345 
2346 		} break;
2347 
2348 		case FILE_SAVE_ALL_SCENES: {
2349 
2350 			_save_all_scenes();
2351 		} break;
2352 		case FILE_SAVE_BEFORE_RUN: {
2353 			if (!p_confirmed) {
2354 				confirmation->get_cancel()->set_text(TTR("No"));
2355 				confirmation->get_ok()->set_text(TTR("Yes"));
2356 				confirmation->set_text(TTR("This scene has never been saved. Save before running?"));
2357 				confirmation->popup_centered_minsize();
2358 				break;
2359 			}
2360 
2361 			_menu_option(FILE_SAVE_AS_SCENE);
2362 			_menu_option_confirm(FILE_SAVE_AND_RUN, false);
2363 		} break;
2364 
2365 		case FILE_EXPORT_PROJECT: {
2366 
2367 			project_export->popup_export();
2368 		} break;
2369 
2370 		case FILE_EXPORT_MESH_LIBRARY: {
2371 
2372 			if (!editor_data.get_edited_scene_root()) {
2373 
2374 				show_accept(TTR("This operation can't be done without a scene."), TTR("OK"));
2375 				break;
2376 			}
2377 
2378 			List<String> extensions;
2379 			Ref<MeshLibrary> ml(memnew(MeshLibrary));
2380 			ResourceSaver::get_recognized_extensions(ml, &extensions);
2381 			file_export_lib->clear_filters();
2382 			for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
2383 				file_export_lib->add_filter("*." + E->get());
2384 			}
2385 
2386 			file_export_lib->popup_centered_ratio();
2387 			file_export_lib->set_title(TTR("Export Mesh Library"));
2388 
2389 		} break;
2390 		case FILE_EXPORT_TILESET: {
2391 
2392 			//Make sure that the scene has a root before trying to convert to tileset
2393 			if (!editor_data.get_edited_scene_root()) {
2394 				show_accept(TTR("This operation can't be done without a root node."), TTR("OK"));
2395 				break;
2396 			}
2397 
2398 			List<String> extensions;
2399 			Ref<TileSet> ml(memnew(TileSet));
2400 			ResourceSaver::get_recognized_extensions(ml, &extensions);
2401 			file_export_lib->clear_filters();
2402 			for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
2403 				file_export_lib->add_filter("*." + E->get());
2404 			}
2405 
2406 			file_export_lib->popup_centered_ratio();
2407 			file_export_lib->set_title(TTR("Export Tile Set"));
2408 
2409 		} break;
2410 
2411 		case FILE_IMPORT_SUBSCENE: {
2412 
2413 			if (!editor_data.get_edited_scene_root()) {
2414 
2415 				show_accept(TTR("This operation can't be done without a selected node."), TTR("OK"));
2416 				break;
2417 			}
2418 
2419 			scene_tree_dock->import_subscene();
2420 
2421 		} break;
2422 
2423 		case FILE_EXTERNAL_OPEN_SCENE: {
2424 
2425 			if (unsaved_cache && !p_confirmed) {
2426 
2427 				confirmation->get_ok()->set_text(TTR("Open"));
2428 				confirmation->set_text(TTR("Current scene not saved. Open anyway?"));
2429 				confirmation->popup_centered_minsize();
2430 				break;
2431 			}
2432 
2433 			bool oprev = opening_prev;
2434 			Error err = load_scene(external_file);
2435 			if (err == OK && oprev) {
2436 				previous_scenes.pop_back();
2437 				opening_prev = false;
2438 			}
2439 
2440 		} break;
2441 
2442 		case EDIT_UNDO: {
2443 
2444 			if (Input::get_singleton()->get_mouse_button_mask() & 0x7) {
2445 				log->add_message("Can't undo while mouse buttons are pressed.", EditorLog::MSG_TYPE_EDITOR);
2446 			} else {
2447 				String action = editor_data.get_undo_redo().get_current_action_name();
2448 
2449 				if (!editor_data.get_undo_redo().undo()) {
2450 					log->add_message("Nothing to undo.", EditorLog::MSG_TYPE_EDITOR);
2451 				} else if (action != "") {
2452 					log->add_message("Undo: " + action, EditorLog::MSG_TYPE_EDITOR);
2453 				}
2454 			}
2455 		} break;
2456 		case EDIT_REDO: {
2457 
2458 			if (Input::get_singleton()->get_mouse_button_mask() & 0x7) {
2459 				log->add_message("Can't redo while mouse buttons are pressed.", EditorLog::MSG_TYPE_EDITOR);
2460 			} else {
2461 				if (!editor_data.get_undo_redo().redo()) {
2462 					log->add_message("Nothing to redo.", EditorLog::MSG_TYPE_EDITOR);
2463 				} else {
2464 					String action = editor_data.get_undo_redo().get_current_action_name();
2465 					log->add_message("Redo: " + action, EditorLog::MSG_TYPE_EDITOR);
2466 				}
2467 			}
2468 		} break;
2469 
2470 		case EDIT_RELOAD_SAVED_SCENE: {
2471 
2472 			Node *scene = get_edited_scene();
2473 
2474 			if (!scene)
2475 				break;
2476 
2477 			String filename = scene->get_filename();
2478 
2479 			if (filename == String()) {
2480 				show_warning(TTR("Can't reload a scene that was never saved."));
2481 				break;
2482 			}
2483 
2484 			if (unsaved_cache && !p_confirmed) {
2485 				confirmation->get_ok()->set_text(TTR("Reload Saved Scene"));
2486 				confirmation->set_text(
2487 						TTR("The current scene has unsaved changes.\nReload the saved scene anyway? This action cannot be undone."));
2488 				confirmation->popup_centered_minsize();
2489 				break;
2490 			}
2491 
2492 			int cur_idx = editor_data.get_edited_scene();
2493 			_remove_edited_scene();
2494 			Error err = load_scene(filename);
2495 			if (err != OK)
2496 				ERR_PRINT("Failed to load scene");
2497 			editor_data.move_edited_scene_to_index(cur_idx);
2498 			get_undo_redo()->clear_history(false);
2499 			scene_tabs->set_current_tab(cur_idx);
2500 
2501 		} break;
2502 		case RUN_PLAY: {
2503 			run_play();
2504 
2505 		} break;
2506 		case RUN_PLAY_CUSTOM_SCENE: {
2507 			if (run_custom_filename.empty() || editor_run.get_status() == EditorRun::STATUS_STOP) {
2508 				_menu_option_confirm(RUN_STOP, true);
2509 				quick_run->popup_dialog("PackedScene", true);
2510 				quick_run->set_title(TTR("Quick Run Scene..."));
2511 				play_custom_scene_button->set_pressed(false);
2512 			} else {
2513 				String last_custom_scene = run_custom_filename;
2514 				run_play_custom(last_custom_scene);
2515 			}
2516 
2517 		} break;
2518 		case RUN_STOP: {
2519 
2520 			if (editor_run.get_status() == EditorRun::STATUS_STOP)
2521 				break;
2522 
2523 			editor_run.stop();
2524 			run_custom_filename.clear();
2525 			play_button->set_pressed(false);
2526 			play_button->set_icon(gui_base->get_icon("MainPlay", "EditorIcons"));
2527 			play_scene_button->set_pressed(false);
2528 			play_scene_button->set_icon(gui_base->get_icon("PlayScene", "EditorIcons"));
2529 			play_custom_scene_button->set_pressed(false);
2530 			play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons"));
2531 			stop_button->set_disabled(true);
2532 
2533 			if (bool(EDITOR_GET("run/output/always_close_output_on_stop"))) {
2534 				for (int i = 0; i < bottom_panel_items.size(); i++) {
2535 					if (bottom_panel_items[i].control == log) {
2536 						_bottom_panel_switch(false, i);
2537 						break;
2538 					}
2539 				}
2540 			}
2541 			emit_signal("stop_pressed");
2542 
2543 		} break;
2544 
2545 		case FILE_SHOW_IN_FILESYSTEM: {
2546 			String path = editor_data.get_scene_path(editor_data.get_edited_scene());
2547 			if (path != String()) {
2548 				filesystem_dock->navigate_to_path(path);
2549 			}
2550 		} break;
2551 
2552 		case RUN_PLAY_SCENE: {
2553 			run_play_current();
2554 
2555 		} break;
2556 		case RUN_PLAY_NATIVE: {
2557 
2558 			bool autosave = EDITOR_GET("run/auto_save/save_before_running");
2559 			if (autosave) {
2560 				_menu_option_confirm(FILE_SAVE_ALL_SCENES, false);
2561 			}
2562 			if (run_native->is_deploy_debug_remote_enabled()) {
2563 				_menu_option_confirm(RUN_STOP, true);
2564 
2565 				if (!call_build())
2566 					break; // build failed
2567 
2568 				emit_signal("play_pressed");
2569 				editor_run.run_native_notify();
2570 			}
2571 		} break;
2572 		case RUN_SCENE_SETTINGS: {
2573 
2574 			run_settings_dialog->popup_run_settings();
2575 		} break;
2576 		case RUN_SETTINGS: {
2577 
2578 			project_settings->popup_project_settings();
2579 		} break;
2580 		case FILE_INSTALL_ANDROID_SOURCE: {
2581 
2582 			if (p_confirmed) {
2583 				export_template_manager->install_android_template();
2584 			} else {
2585 				if (DirAccess::exists("res://android/build")) {
2586 					remove_android_build_template->popup_centered_minsize();
2587 				} else if (export_template_manager->can_install_android_template()) {
2588 					install_android_build_template->popup_centered_minsize();
2589 				} else {
2590 					custom_build_manage_templates->popup_centered_minsize();
2591 				}
2592 			}
2593 		} break;
2594 		case RUN_PROJECT_DATA_FOLDER: {
2595 			OS::get_singleton()->shell_open(String("file://") + OS::get_singleton()->get_user_data_dir());
2596 		} break;
2597 		case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES: {
2598 			OS::get_singleton()->shell_open("file://" + ProjectSettings::get_singleton()->get_resource_path().plus_file("android"));
2599 		} break;
2600 		case FILE_QUIT:
2601 		case RUN_PROJECT_MANAGER: {
2602 
2603 			if (!p_confirmed) {
2604 				bool save_each = EDITOR_GET("interface/editor/save_each_scene_on_quit");
2605 				if (_next_unsaved_scene(!save_each) == -1) {
2606 
2607 					bool confirm = EDITOR_GET("interface/editor/quit_confirmation");
2608 					if (confirm) {
2609 
2610 						confirmation->get_ok()->set_text(p_option == FILE_QUIT ? TTR("Quit") : TTR("Yes"));
2611 						confirmation->set_text(p_option == FILE_QUIT ? TTR("Exit the editor?") : TTR("Open Project Manager?"));
2612 						confirmation->popup_centered_minsize();
2613 					} else {
2614 						_discard_changes();
2615 						break;
2616 					}
2617 				} else {
2618 
2619 					if (save_each) {
2620 
2621 						_menu_option_confirm(p_option == FILE_QUIT ? FILE_CLOSE_ALL_AND_QUIT : FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER, false);
2622 					} else {
2623 
2624 						String unsaved_scenes;
2625 						int i = _next_unsaved_scene(true, 0);
2626 						while (i != -1) {
2627 							unsaved_scenes += "\n            " + editor_data.get_edited_scene_root(i)->get_filename();
2628 							i = _next_unsaved_scene(true, ++i);
2629 						}
2630 
2631 						save_confirmation->get_ok()->set_text(TTR("Save & Quit"));
2632 						save_confirmation->set_text((p_option == FILE_QUIT ? TTR("Save changes to the following scene(s) before quitting?") : TTR("Save changes the following scene(s) before opening Project Manager?")) + unsaved_scenes);
2633 						save_confirmation->popup_centered_minsize();
2634 					}
2635 				}
2636 
2637 				OS::get_singleton()->request_attention();
2638 				break;
2639 			}
2640 
2641 			if (_next_unsaved_scene(true) != -1) {
2642 				_save_all_scenes();
2643 			}
2644 			_discard_changes();
2645 		} break;
2646 		case RUN_FILE_SERVER: {
2647 
2648 			bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_FILE_SERVER));
2649 
2650 			if (ischecked) {
2651 				file_server->stop();
2652 				run_native->set_deploy_dumb(false);
2653 			} else {
2654 				file_server->start();
2655 				run_native->set_deploy_dumb(true);
2656 			}
2657 
2658 			debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_FILE_SERVER), !ischecked);
2659 			EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_file_server", !ischecked);
2660 		} break;
2661 		case RUN_LIVE_DEBUG: {
2662 
2663 			bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_LIVE_DEBUG));
2664 
2665 			debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_LIVE_DEBUG), !ischecked);
2666 			ScriptEditor::get_singleton()->get_debugger()->set_live_debugging(!ischecked);
2667 			EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_live_debug", !ischecked);
2668 
2669 		} break;
2670 		case RUN_DEPLOY_REMOTE_DEBUG: {
2671 
2672 			bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEPLOY_REMOTE_DEBUG));
2673 			debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEPLOY_REMOTE_DEBUG), !ischecked);
2674 			run_native->set_deploy_debug_remote(!ischecked);
2675 			EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_deploy_remote_debug", !ischecked);
2676 
2677 		} break;
2678 		case RUN_DEBUG_COLLISONS: {
2679 
2680 			bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_COLLISONS));
2681 			debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_COLLISONS), !ischecked);
2682 			run_native->set_debug_collisions(!ischecked);
2683 			editor_run.set_debug_collisions(!ischecked);
2684 			EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_debug_collisons", !ischecked);
2685 
2686 		} break;
2687 		case RUN_DEBUG_NAVIGATION: {
2688 
2689 			bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_NAVIGATION));
2690 			debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_NAVIGATION), !ischecked);
2691 			run_native->set_debug_navigation(!ischecked);
2692 			editor_run.set_debug_navigation(!ischecked);
2693 			EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_debug_navigation", !ischecked);
2694 
2695 		} break;
2696 		case RUN_RELOAD_SCRIPTS: {
2697 
2698 			bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_RELOAD_SCRIPTS));
2699 			debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_RELOAD_SCRIPTS), !ischecked);
2700 
2701 			ScriptEditor::get_singleton()->set_live_auto_reload_running_scripts(!ischecked);
2702 			EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_reload_scripts", !ischecked);
2703 
2704 		} break;
2705 		case SETTINGS_UPDATE_CONTINUOUSLY: {
2706 
2707 			EditorSettings::get_singleton()->set("interface/editor/update_continuously", true);
2708 			_update_update_spinner();
2709 			show_accept(TTR("This option is deprecated. Situations where refresh must be forced are now considered a bug. Please report."), TTR("OK"));
2710 		} break;
2711 		case SETTINGS_UPDATE_WHEN_CHANGED: {
2712 
2713 			EditorSettings::get_singleton()->set("interface/editor/update_continuously", false);
2714 			_update_update_spinner();
2715 		} break;
2716 		case SETTINGS_UPDATE_SPINNER_HIDE: {
2717 
2718 			EditorSettings::get_singleton()->set("interface/editor/show_update_spinner", false);
2719 			_update_update_spinner();
2720 		} break;
2721 		case SETTINGS_PREFERENCES: {
2722 
2723 			settings_config_dialog->popup_edit_settings();
2724 		} break;
2725 		case SETTINGS_EDITOR_DATA_FOLDER: {
2726 
2727 			OS::get_singleton()->shell_open(String("file://") + EditorSettings::get_singleton()->get_data_dir());
2728 		} break;
2729 		case SETTINGS_EDITOR_CONFIG_FOLDER: {
2730 
2731 			OS::get_singleton()->shell_open(String("file://") + EditorSettings::get_singleton()->get_settings_dir());
2732 		} break;
2733 		case SETTINGS_MANAGE_EXPORT_TEMPLATES: {
2734 
2735 			export_template_manager->popup_manager();
2736 
2737 		} break;
2738 		case SETTINGS_MANAGE_FEATURE_PROFILES: {
2739 
2740 			feature_profile_manager->popup_centered_clamped(Size2(900, 800) * EDSCALE, 0.8);
2741 		} break;
2742 		case SETTINGS_TOGGLE_FULLSCREEN: {
2743 
2744 			OS::get_singleton()->set_window_fullscreen(!OS::get_singleton()->is_window_fullscreen());
2745 
2746 		} break;
2747 		case SETTINGS_TOGGLE_CONSOLE: {
2748 
2749 			bool was_visible = OS::get_singleton()->is_console_visible();
2750 			OS::get_singleton()->set_console_visible(!was_visible);
2751 			EditorSettings::get_singleton()->set_setting("interface/editor/hide_console_window", was_visible);
2752 		} break;
2753 		case EDITOR_SCREENSHOT: {
2754 
2755 			screenshot_timer->start();
2756 		} break;
2757 		case SETTINGS_PICK_MAIN_SCENE: {
2758 
2759 			file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
2760 			List<String> extensions;
2761 			ResourceLoader::get_recognized_extensions_for_type("PackedScene", &extensions);
2762 			file->clear_filters();
2763 			for (int i = 0; i < extensions.size(); i++) {
2764 
2765 				file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
2766 			}
2767 
2768 			Node *scene = editor_data.get_edited_scene_root();
2769 			if (scene) {
2770 				file->set_current_path(scene->get_filename());
2771 			};
2772 			file->set_title(TTR("Pick a Main Scene"));
2773 			file->popup_centered_ratio();
2774 
2775 		} break;
2776 		case HELP_SEARCH: {
2777 			emit_signal("request_help_search", "");
2778 		} break;
2779 		case HELP_DOCS: {
2780 			OS::get_singleton()->shell_open("https://docs.godotengine.org/");
2781 		} break;
2782 		case HELP_QA: {
2783 			OS::get_singleton()->shell_open("https://godotengine.org/qa/");
2784 		} break;
2785 		case HELP_REPORT_A_BUG: {
2786 			OS::get_singleton()->shell_open("https://github.com/godotengine/godot/issues");
2787 		} break;
2788 		case HELP_SEND_DOCS_FEEDBACK: {
2789 			OS::get_singleton()->shell_open("https://github.com/godotengine/godot-docs/issues");
2790 		} break;
2791 		case HELP_COMMUNITY: {
2792 			OS::get_singleton()->shell_open("https://godotengine.org/community");
2793 		} break;
2794 		case HELP_ABOUT: {
2795 			about->popup_centered_minsize(Size2(780, 500) * EDSCALE);
2796 		} break;
2797 
2798 		case SET_VIDEO_DRIVER_SAVE_AND_RESTART: {
2799 
2800 			ProjectSettings::get_singleton()->set("rendering/quality/driver/driver_name", video_driver_request);
2801 			ProjectSettings::get_singleton()->save();
2802 
2803 			save_all_scenes();
2804 			restart_editor();
2805 		} break;
2806 	}
2807 }
2808 
_request_screenshot()2809 void EditorNode::_request_screenshot() {
2810 	_screenshot();
2811 }
2812 
_screenshot(bool p_use_utc)2813 void EditorNode::_screenshot(bool p_use_utc) {
2814 	String name = "editor_screenshot_" + OS::get_singleton()->get_iso_date_time(p_use_utc).replace(":", "") + ".png";
2815 	NodePath path = String("user://") + name;
2816 	_save_screenshot(path);
2817 	if (EditorSettings::get_singleton()->get("interface/editor/automatically_open_screenshots")) {
2818 		OS::get_singleton()->shell_open(String("file://") + ProjectSettings::get_singleton()->globalize_path(path));
2819 	}
2820 }
2821 
_save_screenshot(NodePath p_path)2822 void EditorNode::_save_screenshot(NodePath p_path) {
2823 
2824 	Viewport *viewport = EditorInterface::get_singleton()->get_editor_viewport()->get_viewport();
2825 	viewport->set_clear_mode(Viewport::CLEAR_MODE_ONLY_NEXT_FRAME);
2826 	Ref<Image> img = viewport->get_texture()->get_data();
2827 	img->flip_y();
2828 	viewport->set_clear_mode(Viewport::CLEAR_MODE_ALWAYS);
2829 	Error error = img->save_png(p_path);
2830 	ERR_FAIL_COND_MSG(error != OK, "Cannot save screenshot to file '" + p_path + "'.");
2831 }
2832 
_tool_menu_option(int p_idx)2833 void EditorNode::_tool_menu_option(int p_idx) {
2834 	switch (tool_menu->get_item_id(p_idx)) {
2835 		case TOOLS_ORPHAN_RESOURCES: {
2836 			orphan_resources->show();
2837 		} break;
2838 		case TOOLS_CUSTOM: {
2839 			if (tool_menu->get_item_submenu(p_idx) == "") {
2840 				Array params = tool_menu->get_item_metadata(p_idx);
2841 
2842 				Object *handler = ObjectDB::get_instance(params[0]);
2843 				String callback = params[1];
2844 				Variant *ud = &params[2];
2845 				Variant::CallError ce;
2846 
2847 				handler->call(callback, (const Variant **)&ud, 1, ce);
2848 				if (ce.error != Variant::CallError::CALL_OK) {
2849 					String err = Variant::get_call_error_text(handler, callback, (const Variant **)&ud, 1, ce);
2850 					ERR_PRINTS("Error calling function from tool menu: " + err);
2851 				}
2852 			} // else it's a submenu so don't do anything.
2853 		} break;
2854 	}
2855 }
2856 
_next_unsaved_scene(bool p_valid_filename,int p_start)2857 int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) {
2858 
2859 	for (int i = p_start; i < editor_data.get_edited_scene_count(); i++) {
2860 
2861 		if (!editor_data.get_edited_scene_root(i))
2862 			continue;
2863 		int current = editor_data.get_edited_scene();
2864 		bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0;
2865 		if (unsaved) {
2866 			String scene_filename = editor_data.get_edited_scene_root(i)->get_filename();
2867 			if (p_valid_filename && scene_filename.length() == 0)
2868 				continue;
2869 			return i;
2870 		}
2871 	}
2872 	return -1;
2873 }
2874 
_exit_editor()2875 void EditorNode::_exit_editor() {
2876 	exiting = true;
2877 	resource_preview->stop(); //stop early to avoid crashes
2878 	_save_docks();
2879 
2880 	// Dim the editor window while it's quitting to make it clearer that it's busy
2881 	dim_editor(true, true);
2882 
2883 	get_tree()->quit();
2884 }
2885 
_discard_changes(const String & p_str)2886 void EditorNode::_discard_changes(const String &p_str) {
2887 
2888 	switch (current_option) {
2889 
2890 		case FILE_CLOSE_ALL_AND_QUIT:
2891 		case FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER:
2892 		case FILE_CLOSE:
2893 		case FILE_CLOSE_OTHERS:
2894 		case FILE_CLOSE_RIGHT:
2895 		case FILE_CLOSE_ALL:
2896 		case SCENE_TAB_CLOSE: {
2897 
2898 			Node *scene = editor_data.get_edited_scene_root(tab_closing);
2899 			if (scene != NULL) {
2900 				String scene_filename = scene->get_filename();
2901 				if (scene_filename != "") {
2902 					previous_scenes.push_back(scene_filename);
2903 				}
2904 			}
2905 
2906 			_remove_scene(tab_closing);
2907 			_update_scene_tabs();
2908 
2909 			if (current_option == FILE_CLOSE_ALL_AND_QUIT || current_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER) {
2910 				if (_next_unsaved_scene(false) == -1) {
2911 					current_option = current_option == FILE_CLOSE_ALL_AND_QUIT ? FILE_QUIT : RUN_PROJECT_MANAGER;
2912 					_discard_changes();
2913 				} else {
2914 					_menu_option_confirm(current_option, false);
2915 				}
2916 			} else if (current_option == FILE_CLOSE_OTHERS || current_option == FILE_CLOSE_RIGHT) {
2917 				if (editor_data.get_edited_scene_count() == 1 || (current_option == FILE_CLOSE_RIGHT && editor_data.get_edited_scene_count() <= editor_data.get_edited_scene() + 1)) {
2918 					current_option = -1;
2919 					save_confirmation->hide();
2920 				} else {
2921 					_menu_option_confirm(current_option, false);
2922 				}
2923 			} else if (current_option == FILE_CLOSE_ALL && editor_data.get_edited_scene_count() > 0) {
2924 				_menu_option_confirm(current_option, false);
2925 			} else {
2926 				current_option = -1;
2927 				save_confirmation->hide();
2928 			}
2929 		} break;
2930 		case FILE_QUIT: {
2931 
2932 			_menu_option_confirm(RUN_STOP, true);
2933 			_exit_editor();
2934 
2935 		} break;
2936 		case RUN_PROJECT_MANAGER: {
2937 
2938 			_menu_option_confirm(RUN_STOP, true);
2939 			_exit_editor();
2940 			String exec = OS::get_singleton()->get_executable_path();
2941 
2942 			List<String> args;
2943 			args.push_back("--path");
2944 			args.push_back(exec.get_base_dir());
2945 			args.push_back("--project-manager");
2946 
2947 			OS::ProcessID pid = 0;
2948 			Error err = OS::get_singleton()->execute(exec, args, false, &pid);
2949 			ERR_FAIL_COND(err);
2950 		} break;
2951 	}
2952 }
2953 
_update_debug_options()2954 void EditorNode::_update_debug_options() {
2955 
2956 	bool check_deploy_remote = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_deploy_remote_debug", false);
2957 	bool check_file_server = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_file_server", false);
2958 	bool check_debug_collisons = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_collisons", false);
2959 	bool check_debug_navigation = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_navigation", false);
2960 	bool check_live_debug = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_live_debug", true);
2961 	bool check_reload_scripts = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_reload_scripts", true);
2962 
2963 	if (check_deploy_remote) _menu_option_confirm(RUN_DEPLOY_REMOTE_DEBUG, true);
2964 	if (check_file_server) _menu_option_confirm(RUN_FILE_SERVER, true);
2965 	if (check_debug_collisons) _menu_option_confirm(RUN_DEBUG_COLLISONS, true);
2966 	if (check_debug_navigation) _menu_option_confirm(RUN_DEBUG_NAVIGATION, true);
2967 	if (check_live_debug) _menu_option_confirm(RUN_LIVE_DEBUG, true);
2968 	if (check_reload_scripts) _menu_option_confirm(RUN_RELOAD_SCRIPTS, true);
2969 }
2970 
_update_file_menu_opened()2971 void EditorNode::_update_file_menu_opened() {
2972 
2973 	Ref<ShortCut> close_scene_sc = ED_GET_SHORTCUT("editor/close_scene");
2974 	close_scene_sc->set_name(TTR("Close Scene"));
2975 	Ref<ShortCut> reopen_closed_scene_sc = ED_GET_SHORTCUT("editor/reopen_closed_scene");
2976 	reopen_closed_scene_sc->set_name(TTR("Reopen Closed Scene"));
2977 	PopupMenu *pop = file_menu->get_popup();
2978 	pop->set_item_disabled(pop->get_item_index(FILE_OPEN_PREV), previous_scenes.empty());
2979 }
2980 
_update_file_menu_closed()2981 void EditorNode::_update_file_menu_closed() {
2982 	PopupMenu *pop = file_menu->get_popup();
2983 	pop->set_item_disabled(pop->get_item_index(FILE_OPEN_PREV), false);
2984 }
2985 
get_viewport()2986 Control *EditorNode::get_viewport() {
2987 
2988 	return viewport;
2989 }
2990 
_editor_select(int p_which)2991 void EditorNode::_editor_select(int p_which) {
2992 
2993 	static bool selecting = false;
2994 	if (selecting || changing_scene)
2995 		return;
2996 
2997 	ERR_FAIL_INDEX(p_which, editor_table.size());
2998 
2999 	if (!main_editor_buttons[p_which]->is_visible()) //button hidden, no editor
3000 		return;
3001 
3002 	selecting = true;
3003 
3004 	for (int i = 0; i < main_editor_buttons.size(); i++) {
3005 		main_editor_buttons[i]->set_pressed(i == p_which);
3006 	}
3007 
3008 	selecting = false;
3009 
3010 	EditorPlugin *new_editor = editor_table[p_which];
3011 	ERR_FAIL_COND(!new_editor);
3012 
3013 	if (editor_plugin_screen == new_editor)
3014 		return;
3015 
3016 	if (editor_plugin_screen) {
3017 		editor_plugin_screen->make_visible(false);
3018 	}
3019 
3020 	editor_plugin_screen = new_editor;
3021 	editor_plugin_screen->make_visible(true);
3022 	editor_plugin_screen->selected_notify();
3023 
3024 	int plugin_count = editor_data.get_editor_plugin_count();
3025 	for (int i = 0; i < plugin_count; i++) {
3026 		editor_data.get_editor_plugin(i)->notify_main_screen_changed(editor_plugin_screen->get_name());
3027 	}
3028 
3029 	if (EditorSettings::get_singleton()->get("interface/editor/separate_distraction_mode")) {
3030 		if (p_which == EDITOR_SCRIPT) {
3031 			set_distraction_free_mode(script_distraction);
3032 		} else {
3033 			set_distraction_free_mode(scene_distraction);
3034 		}
3035 	}
3036 }
3037 
select_editor_by_name(const String & p_name)3038 void EditorNode::select_editor_by_name(const String &p_name) {
3039 	ERR_FAIL_COND(p_name == "");
3040 
3041 	for (int i = 0; i < main_editor_buttons.size(); i++) {
3042 		if (main_editor_buttons[i]->get_text() == p_name) {
3043 			_editor_select(i);
3044 			return;
3045 		}
3046 	}
3047 
3048 	ERR_FAIL_MSG("The editor name '" + p_name + "' was not found.");
3049 }
3050 
add_editor_plugin(EditorPlugin * p_editor,bool p_config_changed)3051 void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed) {
3052 
3053 	if (p_editor->has_main_screen()) {
3054 
3055 		ToolButton *tb = memnew(ToolButton);
3056 		tb->set_toggle_mode(true);
3057 		tb->connect("pressed", singleton, "_editor_select", varray(singleton->main_editor_buttons.size()));
3058 		tb->set_text(p_editor->get_name());
3059 		Ref<Texture> icon = p_editor->get_icon();
3060 
3061 		if (icon.is_valid()) {
3062 			tb->set_icon(icon);
3063 		} else if (singleton->gui_base->has_icon(p_editor->get_name(), "EditorIcons")) {
3064 			tb->set_icon(singleton->gui_base->get_icon(p_editor->get_name(), "EditorIcons"));
3065 		}
3066 
3067 		tb->set_name(p_editor->get_name());
3068 		singleton->main_editor_buttons.push_back(tb);
3069 		singleton->main_editor_button_vb->add_child(tb);
3070 		singleton->editor_table.push_back(p_editor);
3071 
3072 		singleton->distraction_free->raise();
3073 	}
3074 	singleton->editor_data.add_editor_plugin(p_editor);
3075 	singleton->add_child(p_editor);
3076 	if (p_config_changed)
3077 		p_editor->enable_plugin();
3078 }
3079 
remove_editor_plugin(EditorPlugin * p_editor,bool p_config_changed)3080 void EditorNode::remove_editor_plugin(EditorPlugin *p_editor, bool p_config_changed) {
3081 
3082 	if (p_editor->has_main_screen()) {
3083 
3084 		for (int i = 0; i < singleton->main_editor_buttons.size(); i++) {
3085 
3086 			if (p_editor->get_name() == singleton->main_editor_buttons[i]->get_text()) {
3087 
3088 				if (singleton->main_editor_buttons[i]->is_pressed()) {
3089 					singleton->_editor_select(EDITOR_SCRIPT);
3090 				}
3091 
3092 				memdelete(singleton->main_editor_buttons[i]);
3093 				singleton->main_editor_buttons.remove(i);
3094 
3095 				break;
3096 			}
3097 		}
3098 
3099 		singleton->editor_table.erase(p_editor);
3100 	}
3101 	p_editor->make_visible(false);
3102 	p_editor->clear();
3103 	if (p_config_changed)
3104 		p_editor->disable_plugin();
3105 	singleton->editor_plugins_over->get_plugins_list().erase(p_editor);
3106 	singleton->remove_child(p_editor);
3107 	singleton->editor_data.remove_editor_plugin(p_editor);
3108 	singleton->get_editor_plugins_force_input_forwarding()->remove_plugin(p_editor);
3109 }
3110 
_update_addon_config()3111 void EditorNode::_update_addon_config() {
3112 
3113 	if (_initializing_addons)
3114 		return;
3115 
3116 	Vector<String> enabled_addons;
3117 
3118 	for (Map<String, EditorPlugin *>::Element *E = plugin_addons.front(); E; E = E->next()) {
3119 		enabled_addons.push_back(E->key());
3120 	}
3121 
3122 	if (enabled_addons.size() == 0) {
3123 		ProjectSettings::get_singleton()->set("editor_plugins/enabled", Variant());
3124 	} else {
3125 		ProjectSettings::get_singleton()->set("editor_plugins/enabled", enabled_addons);
3126 	}
3127 
3128 	project_settings->queue_save();
3129 }
3130 
set_addon_plugin_enabled(const String & p_addon,bool p_enabled,bool p_config_changed)3131 void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, bool p_config_changed) {
3132 
3133 	ERR_FAIL_COND(p_enabled && plugin_addons.has(p_addon));
3134 	ERR_FAIL_COND(!p_enabled && !plugin_addons.has(p_addon));
3135 
3136 	if (!p_enabled) {
3137 
3138 		EditorPlugin *addon = plugin_addons[p_addon];
3139 		remove_editor_plugin(addon, p_config_changed);
3140 		memdelete(addon); //bye
3141 		plugin_addons.erase(p_addon);
3142 		_update_addon_config();
3143 		return;
3144 	}
3145 
3146 	Ref<ConfigFile> cf;
3147 	cf.instance();
3148 	String addon_path = String("res://addons").plus_file(p_addon).plus_file("plugin.cfg");
3149 	if (!DirAccess::exists(addon_path.get_base_dir())) {
3150 		ProjectSettings *ps = ProjectSettings::get_singleton();
3151 		PoolStringArray enabled_plugins = ps->get("editor_plugins/enabled");
3152 		for (int i = 0; i < enabled_plugins.size(); ++i) {
3153 			if (enabled_plugins.get(i) == p_addon) {
3154 				enabled_plugins.remove(i);
3155 				break;
3156 			}
3157 		}
3158 		ps->set("editor_plugins/enabled", enabled_plugins);
3159 		ps->save();
3160 		WARN_PRINTS("Addon '" + p_addon + "' failed to load. No directory found. Removing from enabled plugins.");
3161 		return;
3162 	}
3163 	Error err = cf->load(addon_path);
3164 	if (err != OK) {
3165 		show_warning(vformat(TTR("Unable to enable addon plugin at: '%s' parsing of config failed."), addon_path));
3166 		return;
3167 	}
3168 
3169 	if (!cf->has_section_key("plugin", "script")) {
3170 		show_warning(vformat(TTR("Unable to find script field for addon plugin at: 'res://addons/%s'."), p_addon));
3171 		return;
3172 	}
3173 
3174 	String script_path = cf->get_value("plugin", "script");
3175 	Ref<Script> script; // We need to save it for creating "ep" below.
3176 
3177 	// Only try to load the script if it has a name. Else, the plugin has no init script.
3178 	if (script_path.length() > 0) {
3179 		script_path = String("res://addons").plus_file(p_addon).plus_file(script_path);
3180 		script = ResourceLoader::load(script_path);
3181 
3182 		if (script.is_null()) {
3183 			show_warning(vformat(TTR("Unable to load addon script from path: '%s'."), script_path));
3184 			return;
3185 		}
3186 
3187 		// Errors in the script cause the base_type to be an empty string.
3188 		if (String(script->get_instance_base_type()) == "") {
3189 			show_warning(vformat(TTR("Unable to load addon script from path: '%s' There seems to be an error in the code, please check the syntax."), script_path));
3190 			return;
3191 		}
3192 
3193 		// Plugin init scripts must inherit from EditorPlugin and be tools.
3194 		if (String(script->get_instance_base_type()) != "EditorPlugin") {
3195 			show_warning(vformat(TTR("Unable to load addon script from path: '%s' Base type is not EditorPlugin."), script_path));
3196 			return;
3197 		}
3198 
3199 		if (!script->is_tool()) {
3200 			show_warning(vformat(TTR("Unable to load addon script from path: '%s' Script is not in tool mode."), script_path));
3201 			return;
3202 		}
3203 	}
3204 
3205 	EditorPlugin *ep = memnew(EditorPlugin);
3206 	ep->set_script(script.get_ref_ptr());
3207 	plugin_addons[p_addon] = ep;
3208 	add_editor_plugin(ep, p_config_changed);
3209 
3210 	_update_addon_config();
3211 }
3212 
is_addon_plugin_enabled(const String & p_addon) const3213 bool EditorNode::is_addon_plugin_enabled(const String &p_addon) const {
3214 
3215 	return plugin_addons.has(p_addon);
3216 }
3217 
_remove_edited_scene(bool p_change_tab)3218 void EditorNode::_remove_edited_scene(bool p_change_tab) {
3219 	int new_index = editor_data.get_edited_scene();
3220 	int old_index = new_index;
3221 
3222 	if (new_index > 0) {
3223 		new_index = new_index - 1;
3224 	} else if (editor_data.get_edited_scene_count() > 1) {
3225 		new_index = 1;
3226 	} else {
3227 		editor_data.add_edited_scene(-1);
3228 		new_index = 1;
3229 	}
3230 
3231 	if (editor_data.get_scene_path(old_index) != String()) {
3232 		ScriptEditor::get_singleton()->close_builtin_scripts_from_scene(editor_data.get_scene_path(old_index));
3233 	}
3234 
3235 	if (p_change_tab) _scene_tab_changed(new_index);
3236 	editor_data.remove_scene(old_index);
3237 	editor_data.get_undo_redo().clear_history(false);
3238 	_update_title();
3239 	_update_scene_tabs();
3240 }
3241 
_remove_scene(int index,bool p_change_tab)3242 void EditorNode::_remove_scene(int index, bool p_change_tab) {
3243 
3244 	if (editor_data.get_edited_scene() == index) {
3245 		//Scene to remove is current scene
3246 		_remove_edited_scene(p_change_tab);
3247 	} else {
3248 		//Scene to remove is not active scene
3249 		editor_data.remove_scene(index);
3250 	}
3251 }
3252 
set_edited_scene(Node * p_scene)3253 void EditorNode::set_edited_scene(Node *p_scene) {
3254 
3255 	if (get_editor_data().get_edited_scene_root()) {
3256 		if (get_editor_data().get_edited_scene_root()->get_parent() == scene_root)
3257 			scene_root->remove_child(get_editor_data().get_edited_scene_root());
3258 	}
3259 	get_editor_data().set_edited_scene_root(p_scene);
3260 
3261 	if (Object::cast_to<Popup>(p_scene))
3262 		Object::cast_to<Popup>(p_scene)->show(); //show popups
3263 	scene_tree_dock->set_edited_scene(p_scene);
3264 	if (get_tree())
3265 		get_tree()->set_edited_scene_root(p_scene);
3266 
3267 	if (p_scene) {
3268 		if (p_scene->get_parent() != scene_root)
3269 			scene_root->add_child(p_scene);
3270 	}
3271 }
3272 
_get_current_main_editor()3273 int EditorNode::_get_current_main_editor() {
3274 
3275 	for (int i = 0; i < editor_table.size(); i++) {
3276 		if (editor_table[i] == editor_plugin_screen)
3277 			return i;
3278 	}
3279 
3280 	return 0;
3281 }
3282 
_get_main_scene_state()3283 Dictionary EditorNode::_get_main_scene_state() {
3284 
3285 	Dictionary state;
3286 	state["main_tab"] = _get_current_main_editor();
3287 	state["scene_tree_offset"] = scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->get_value();
3288 	state["property_edit_offset"] = get_inspector()->get_scroll_offset();
3289 	state["saved_version"] = saved_version;
3290 	state["node_filter"] = scene_tree_dock->get_filter();
3291 	return state;
3292 }
3293 
_set_main_scene_state(Dictionary p_state,Node * p_for_scene)3294 void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
3295 
3296 	if (get_edited_scene() != p_for_scene && p_for_scene != NULL)
3297 		return; //not for this scene
3298 
3299 	changing_scene = false;
3300 
3301 	int current = -1;
3302 	for (int i = 0; i < editor_table.size(); i++) {
3303 		if (editor_plugin_screen == editor_table[i]) {
3304 			current = i;
3305 			break;
3306 		}
3307 	}
3308 
3309 	if (p_state.has("editor_index")) {
3310 		int index = p_state["editor_index"];
3311 		if (current < 2) { //if currently in spatial/2d, only switch to spatial/2d. if currently in script, stay there
3312 			if (index < 2 || !get_edited_scene()) {
3313 				_editor_select(index);
3314 			}
3315 		}
3316 	}
3317 
3318 	if (get_edited_scene()) {
3319 		if (current < 2) {
3320 			//use heuristic instead
3321 			int n2d = 0, n3d = 0;
3322 			_find_node_types(get_edited_scene(), n2d, n3d);
3323 			if (n2d > n3d) {
3324 				_editor_select(EDITOR_2D);
3325 			} else if (n3d > n2d) {
3326 				_editor_select(EDITOR_3D);
3327 			}
3328 		}
3329 	}
3330 
3331 	if (p_state.has("scene_tree_offset"))
3332 		scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->set_value(p_state["scene_tree_offset"]);
3333 	if (p_state.has("property_edit_offset"))
3334 		get_inspector()->set_scroll_offset(p_state["property_edit_offset"]);
3335 
3336 	if (p_state.has("node_filter"))
3337 		scene_tree_dock->set_filter(p_state["node_filter"]);
3338 
3339 	//this should only happen at the very end
3340 
3341 	ScriptEditor::get_singleton()->get_debugger()->update_live_edit_root();
3342 	ScriptEditor::get_singleton()->set_scene_root_script(editor_data.get_scene_root_script(editor_data.get_edited_scene()));
3343 	editor_data.notify_edited_scene_changed();
3344 }
3345 
set_current_version(uint64_t p_version)3346 void EditorNode::set_current_version(uint64_t p_version) {
3347 
3348 	saved_version = p_version;
3349 	editor_data.set_edited_scene_version(p_version);
3350 }
3351 
is_changing_scene() const3352 bool EditorNode::is_changing_scene() const {
3353 	return changing_scene;
3354 }
3355 
_clear_undo_history()3356 void EditorNode::_clear_undo_history() {
3357 
3358 	get_undo_redo()->clear_history(false);
3359 }
3360 
set_current_scene(int p_idx)3361 void EditorNode::set_current_scene(int p_idx) {
3362 
3363 	//Save the folding in case the scene gets reloaded.
3364 	if (editor_data.get_scene_path(p_idx) != "" && editor_data.get_edited_scene_root(p_idx))
3365 		editor_folding.save_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx));
3366 
3367 	if (editor_data.check_and_update_scene(p_idx)) {
3368 		if (editor_data.get_scene_path(p_idx) != "")
3369 			editor_folding.load_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx));
3370 
3371 		call_deferred("_clear_undo_history");
3372 	}
3373 
3374 	changing_scene = true;
3375 	editor_data.save_edited_scene_state(editor_selection, &editor_history, _get_main_scene_state());
3376 
3377 	if (get_editor_data().get_edited_scene_root()) {
3378 		if (get_editor_data().get_edited_scene_root()->get_parent() == scene_root)
3379 			scene_root->remove_child(get_editor_data().get_edited_scene_root());
3380 	}
3381 
3382 	editor_selection->clear();
3383 	editor_data.set_edited_scene(p_idx);
3384 
3385 	Node *new_scene = editor_data.get_edited_scene_root();
3386 
3387 	if (Object::cast_to<Popup>(new_scene))
3388 		Object::cast_to<Popup>(new_scene)->show(); //show popups
3389 
3390 	scene_tree_dock->set_edited_scene(new_scene);
3391 	if (get_tree())
3392 		get_tree()->set_edited_scene_root(new_scene);
3393 
3394 	if (new_scene) {
3395 		if (new_scene->get_parent() != scene_root)
3396 			scene_root->add_child(new_scene);
3397 	}
3398 
3399 	Dictionary state = editor_data.restore_edited_scene_state(editor_selection, &editor_history);
3400 	_edit_current();
3401 
3402 	_update_title();
3403 
3404 	call_deferred("_set_main_scene_state", state, get_edited_scene()); //do after everything else is done setting up
3405 }
3406 
is_scene_open(const String & p_path)3407 bool EditorNode::is_scene_open(const String &p_path) {
3408 
3409 	for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
3410 		if (editor_data.get_scene_path(i) == p_path)
3411 			return true;
3412 	}
3413 
3414 	return false;
3415 }
3416 
fix_dependencies(const String & p_for_file)3417 void EditorNode::fix_dependencies(const String &p_for_file) {
3418 	dependency_fixer->edit(p_for_file);
3419 }
3420 
new_scene()3421 int EditorNode::new_scene() {
3422 	int idx = editor_data.add_edited_scene(-1);
3423 	_scene_tab_changed(idx);
3424 	editor_data.clear_editor_states();
3425 	_update_scene_tabs();
3426 	return idx;
3427 }
3428 
load_scene(const String & p_scene,bool p_ignore_broken_deps,bool p_set_inherited,bool p_clear_errors,bool p_force_open_imported)3429 Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, bool p_set_inherited, bool p_clear_errors, bool p_force_open_imported) {
3430 
3431 	if (!is_inside_tree()) {
3432 		defer_load_scene = p_scene;
3433 		return OK;
3434 	}
3435 
3436 	if (!p_set_inherited) {
3437 
3438 		for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
3439 
3440 			if (editor_data.get_scene_path(i) == p_scene) {
3441 				_scene_tab_changed(i);
3442 				return OK;
3443 			}
3444 		}
3445 
3446 		if (!p_force_open_imported && FileAccess::exists(p_scene + ".import")) {
3447 			open_imported->set_text(vformat(TTR("Scene '%s' was automatically imported, so it can't be modified.\nTo make changes to it, a new inherited scene can be created."), p_scene.get_file()));
3448 			open_imported->popup_centered_minsize();
3449 			new_inherited_button->grab_focus();
3450 			open_import_request = p_scene;
3451 			return OK;
3452 		}
3453 	}
3454 
3455 	if (p_clear_errors)
3456 		load_errors->clear();
3457 
3458 	String lpath = ProjectSettings::get_singleton()->localize_path(p_scene);
3459 
3460 	if (!lpath.begins_with("res://")) {
3461 
3462 		show_accept(TTR("Error loading scene, it must be inside the project path. Use 'Import' to open the scene, then save it inside the project path."), TTR("OK"));
3463 		opening_prev = false;
3464 		return ERR_FILE_NOT_FOUND;
3465 	}
3466 
3467 	int prev = editor_data.get_edited_scene();
3468 	int idx = editor_data.add_edited_scene(-1);
3469 
3470 	if (!editor_data.get_edited_scene_root() && editor_data.get_edited_scene_count() == 2) {
3471 		_remove_edited_scene();
3472 	} else {
3473 		_scene_tab_changed(idx);
3474 	}
3475 
3476 	dependency_errors.clear();
3477 
3478 	Error err;
3479 	Ref<PackedScene> sdata = ResourceLoader::load(lpath, "", true, &err);
3480 	if (!sdata.is_valid()) {
3481 
3482 		_dialog_display_load_error(lpath, err);
3483 		opening_prev = false;
3484 
3485 		if (prev != -1) {
3486 			set_current_scene(prev);
3487 			editor_data.remove_scene(idx);
3488 		}
3489 		return ERR_FILE_NOT_FOUND;
3490 	}
3491 
3492 	if (!p_ignore_broken_deps && dependency_errors.has(lpath)) {
3493 
3494 		current_option = -1;
3495 		Vector<String> errors;
3496 		for (Set<String>::Element *E = dependency_errors[lpath].front(); E; E = E->next()) {
3497 
3498 			errors.push_back(E->get());
3499 		}
3500 		dependency_error->show(DependencyErrorDialog::MODE_SCENE, lpath, errors);
3501 		opening_prev = false;
3502 
3503 		if (prev != -1) {
3504 			set_current_scene(prev);
3505 			editor_data.remove_scene(idx);
3506 		}
3507 		return ERR_FILE_MISSING_DEPENDENCIES;
3508 	}
3509 
3510 	dependency_errors.erase(lpath); //at least not self path
3511 
3512 	for (Map<String, Set<String> >::Element *E = dependency_errors.front(); E; E = E->next()) {
3513 
3514 		String txt = vformat(TTR("Scene '%s' has broken dependencies:"), E->key()) + "\n";
3515 		for (Set<String>::Element *F = E->get().front(); F; F = F->next()) {
3516 			txt += "\t" + F->get() + "\n";
3517 		}
3518 		add_io_error(txt);
3519 	}
3520 
3521 	if (ResourceCache::has(lpath)) {
3522 		//used from somewhere else? no problem! update state and replace sdata
3523 		Ref<PackedScene> ps = Ref<PackedScene>(Object::cast_to<PackedScene>(ResourceCache::get(lpath)));
3524 		if (ps.is_valid()) {
3525 			ps->replace_state(sdata->get_state());
3526 			ps->set_last_modified_time(sdata->get_last_modified_time());
3527 			sdata = ps;
3528 		}
3529 
3530 	} else {
3531 		sdata->set_path(lpath, true); //take over path
3532 	}
3533 
3534 	Node *new_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_MAIN);
3535 
3536 	if (!new_scene) {
3537 
3538 		sdata.unref();
3539 		_dialog_display_load_error(lpath, ERR_FILE_CORRUPT);
3540 		opening_prev = false;
3541 		if (prev != -1) {
3542 			set_current_scene(prev);
3543 			editor_data.remove_scene(idx);
3544 		}
3545 		return ERR_FILE_CORRUPT;
3546 	}
3547 
3548 	if (p_set_inherited) {
3549 		Ref<SceneState> state = sdata->get_state();
3550 		state->set_path(lpath);
3551 		new_scene->set_scene_inherited_state(state);
3552 		new_scene->set_filename(String());
3553 	}
3554 
3555 	new_scene->set_scene_instance_state(Ref<SceneState>());
3556 
3557 	set_edited_scene(new_scene);
3558 	_get_scene_metadata(p_scene);
3559 
3560 	saved_version = editor_data.get_undo_redo().get_version();
3561 	_update_title();
3562 	_update_scene_tabs();
3563 	_add_to_recent_scenes(lpath);
3564 
3565 	if (editor_folding.has_folding_data(lpath)) {
3566 		editor_folding.load_scene_folding(new_scene, lpath);
3567 	} else if (EDITOR_GET("interface/inspector/auto_unfold_foreign_scenes")) {
3568 		editor_folding.unfold_scene(new_scene);
3569 		editor_folding.save_scene_folding(new_scene, lpath);
3570 	}
3571 
3572 	prev_scene->set_disabled(previous_scenes.size() == 0);
3573 	opening_prev = false;
3574 	scene_tree_dock->set_selected(new_scene);
3575 
3576 	ScriptEditor::get_singleton()->get_debugger()->update_live_edit_root();
3577 
3578 	push_item(new_scene);
3579 
3580 	if (!restoring_scenes) {
3581 		save_layout();
3582 	}
3583 
3584 	return OK;
3585 }
3586 
open_request(const String & p_path)3587 void EditorNode::open_request(const String &p_path) {
3588 
3589 	if (!opening_prev) {
3590 		List<String>::Element *prev_scene = previous_scenes.find(p_path);
3591 		if (prev_scene != NULL) {
3592 			prev_scene->erase();
3593 		}
3594 	}
3595 
3596 	load_scene(p_path); // as it will be opened in separate tab
3597 }
3598 
request_instance_scene(const String & p_path)3599 void EditorNode::request_instance_scene(const String &p_path) {
3600 
3601 	scene_tree_dock->instance(p_path);
3602 }
3603 
request_instance_scenes(const Vector<String> & p_files)3604 void EditorNode::request_instance_scenes(const Vector<String> &p_files) {
3605 
3606 	scene_tree_dock->instance_scenes(p_files);
3607 }
3608 
get_import_dock()3609 ImportDock *EditorNode::get_import_dock() {
3610 	return import_dock;
3611 }
3612 
get_filesystem_dock()3613 FileSystemDock *EditorNode::get_filesystem_dock() {
3614 
3615 	return filesystem_dock;
3616 }
get_scene_tree_dock()3617 SceneTreeDock *EditorNode::get_scene_tree_dock() {
3618 
3619 	return scene_tree_dock;
3620 }
get_inspector_dock()3621 InspectorDock *EditorNode::get_inspector_dock() {
3622 
3623 	return inspector_dock;
3624 }
3625 
_inherit_request(String p_file)3626 void EditorNode::_inherit_request(String p_file) {
3627 
3628 	current_option = FILE_NEW_INHERITED_SCENE;
3629 	_dialog_action(p_file);
3630 }
3631 
_instance_request(const Vector<String> & p_files)3632 void EditorNode::_instance_request(const Vector<String> &p_files) {
3633 
3634 	request_instance_scenes(p_files);
3635 }
3636 
_close_messages()3637 void EditorNode::_close_messages() {
3638 
3639 	old_split_ofs = center_split->get_split_offset();
3640 	center_split->set_split_offset(0);
3641 }
3642 
_show_messages()3643 void EditorNode::_show_messages() {
3644 
3645 	center_split->set_split_offset(old_split_ofs);
3646 }
3647 
_add_to_recent_scenes(const String & p_scene)3648 void EditorNode::_add_to_recent_scenes(const String &p_scene) {
3649 
3650 	Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scenes", Array());
3651 	if (rc.find(p_scene) != -1)
3652 		rc.erase(p_scene);
3653 	rc.push_front(p_scene);
3654 	if (rc.size() > 10)
3655 		rc.resize(10);
3656 
3657 	EditorSettings::get_singleton()->set_project_metadata("recent_files", "scenes", rc);
3658 	_update_recent_scenes();
3659 }
3660 
_open_recent_scene(int p_idx)3661 void EditorNode::_open_recent_scene(int p_idx) {
3662 
3663 	if (p_idx == recent_scenes->get_item_count() - 1) {
3664 
3665 		EditorSettings::get_singleton()->set_project_metadata("recent_files", "scenes", Array());
3666 		call_deferred("_update_recent_scenes");
3667 	} else {
3668 
3669 		Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scenes", Array());
3670 		ERR_FAIL_INDEX(p_idx, rc.size());
3671 
3672 		if (load_scene(rc[p_idx]) != OK) {
3673 
3674 			rc.remove(p_idx);
3675 			EditorSettings::get_singleton()->set_project_metadata("recent_files", "scenes", rc);
3676 			_update_recent_scenes();
3677 		}
3678 	}
3679 }
3680 
_update_recent_scenes()3681 void EditorNode::_update_recent_scenes() {
3682 
3683 	Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scenes", Array());
3684 	recent_scenes->clear();
3685 
3686 	String path;
3687 	for (int i = 0; i < rc.size(); i++) {
3688 
3689 		path = rc[i];
3690 		recent_scenes->add_item(path.replace("res://", ""), i);
3691 	}
3692 
3693 	recent_scenes->add_separator();
3694 	recent_scenes->add_shortcut(ED_SHORTCUT("editor/clear_recent", TTR("Clear Recent Scenes")));
3695 	recent_scenes->set_as_minsize();
3696 }
3697 
_quick_opened()3698 void EditorNode::_quick_opened() {
3699 
3700 	Vector<String> files = quick_open->get_selected_files();
3701 
3702 	bool open_scene_dialog = quick_open->get_base_type() == "PackedScene";
3703 	for (int i = 0; i < files.size(); i++) {
3704 		String res_path = files[i];
3705 
3706 		List<String> scene_extensions;
3707 		ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions);
3708 
3709 		if (open_scene_dialog || scene_extensions.find(files[i].get_extension())) {
3710 			open_request(res_path);
3711 		} else {
3712 			load_resource(res_path);
3713 		}
3714 	}
3715 }
3716 
_quick_run()3717 void EditorNode::_quick_run() {
3718 
3719 	_run(false, quick_run->get_selected());
3720 }
3721 
notify_child_process_exited()3722 void EditorNode::notify_child_process_exited() {
3723 
3724 	_menu_option_confirm(RUN_STOP, false);
3725 	stop_button->set_pressed(false);
3726 	editor_run.stop();
3727 }
3728 
add_io_error(const String & p_error)3729 void EditorNode::add_io_error(const String &p_error) {
3730 	_load_error_notify(singleton, p_error);
3731 }
3732 
_load_error_notify(void * p_ud,const String & p_text)3733 void EditorNode::_load_error_notify(void *p_ud, const String &p_text) {
3734 
3735 	EditorNode *en = (EditorNode *)p_ud;
3736 	en->load_errors->add_image(en->gui_base->get_icon("Error", "EditorIcons"));
3737 	en->load_errors->add_text(p_text + "\n");
3738 	en->load_error_dialog->popup_centered_ratio(0.5);
3739 }
3740 
_find_scene_in_use(Node * p_node,const String & p_path) const3741 bool EditorNode::_find_scene_in_use(Node *p_node, const String &p_path) const {
3742 
3743 	if (p_node->get_filename() == p_path) {
3744 		return true;
3745 	}
3746 
3747 	for (int i = 0; i < p_node->get_child_count(); i++) {
3748 
3749 		if (_find_scene_in_use(p_node->get_child(i), p_path)) {
3750 			return true;
3751 		}
3752 	}
3753 
3754 	return false;
3755 }
3756 
is_scene_in_use(const String & p_path)3757 bool EditorNode::is_scene_in_use(const String &p_path) {
3758 
3759 	Node *es = get_edited_scene();
3760 	if (es)
3761 		return _find_scene_in_use(es, p_path);
3762 	return false;
3763 }
3764 
register_editor_types()3765 void EditorNode::register_editor_types() {
3766 
3767 	ResourceLoader::set_timestamp_on_load(true);
3768 	ResourceSaver::set_timestamp_on_save(true);
3769 
3770 	ClassDB::register_class<EditorPlugin>();
3771 	ClassDB::register_class<EditorImportPlugin>();
3772 	ClassDB::register_class<EditorScript>();
3773 	ClassDB::register_class<EditorSelection>();
3774 	ClassDB::register_class<EditorFileDialog>();
3775 	ClassDB::register_virtual_class<EditorSettings>();
3776 	ClassDB::register_class<EditorSpatialGizmo>();
3777 	ClassDB::register_class<EditorSpatialGizmoPlugin>();
3778 	ClassDB::register_virtual_class<EditorResourcePreview>();
3779 	ClassDB::register_class<EditorResourcePreviewGenerator>();
3780 	ClassDB::register_virtual_class<EditorFileSystem>();
3781 	ClassDB::register_class<EditorFileSystemDirectory>();
3782 	ClassDB::register_class<EditorVCSInterface>();
3783 	ClassDB::register_virtual_class<ScriptEditor>();
3784 	ClassDB::register_virtual_class<EditorInterface>();
3785 	ClassDB::register_class<EditorExportPlugin>();
3786 	ClassDB::register_class<EditorResourceConversionPlugin>();
3787 	ClassDB::register_class<EditorSceneImporter>();
3788 	ClassDB::register_class<EditorInspector>();
3789 	ClassDB::register_class<EditorInspectorPlugin>();
3790 	ClassDB::register_class<EditorProperty>();
3791 	ClassDB::register_class<AnimationTrackEditPlugin>();
3792 	ClassDB::register_class<ScriptCreateDialog>();
3793 	ClassDB::register_class<EditorFeatureProfile>();
3794 	ClassDB::register_class<EditorSpinSlider>();
3795 	ClassDB::register_virtual_class<FileSystemDock>();
3796 
3797 	// FIXME: Is this stuff obsolete, or should it be ported to new APIs?
3798 	ClassDB::register_class<EditorScenePostImport>();
3799 	//ClassDB::register_type<EditorImportExport>();
3800 }
3801 
unregister_editor_types()3802 void EditorNode::unregister_editor_types() {
3803 
3804 	_init_callbacks.clear();
3805 }
3806 
stop_child_process()3807 void EditorNode::stop_child_process() {
3808 
3809 	_menu_option_confirm(RUN_STOP, false);
3810 }
3811 
get_object_custom_type_base(const Object * p_object) const3812 Ref<Script> EditorNode::get_object_custom_type_base(const Object *p_object) const {
3813 	ERR_FAIL_COND_V(!p_object, NULL);
3814 
3815 	Ref<Script> script = p_object->get_script();
3816 
3817 	if (script.is_valid()) {
3818 		// Uncommenting would break things! Consider adding a parameter if you need it.
3819 		// StringName name = EditorNode::get_editor_data().script_class_get_name(base_script->get_path());
3820 		// if (name != StringName())
3821 		// 	return name;
3822 
3823 		// should probably be deprecated in 4.x
3824 		StringName base = script->get_instance_base_type();
3825 		if (base != StringName() && EditorNode::get_editor_data().get_custom_types().has(base)) {
3826 			const Vector<EditorData::CustomType> &types = EditorNode::get_editor_data().get_custom_types()[base];
3827 
3828 			Ref<Script> base_script = script;
3829 			while (base_script.is_valid()) {
3830 				for (int i = 0; i < types.size(); ++i) {
3831 					if (types[i].script == base_script) {
3832 						return types[i].script;
3833 					}
3834 				}
3835 				base_script = base_script->get_base_script();
3836 			}
3837 		}
3838 	}
3839 
3840 	return NULL;
3841 }
3842 
get_object_custom_type_name(const Object * p_object) const3843 StringName EditorNode::get_object_custom_type_name(const Object *p_object) const {
3844 	ERR_FAIL_COND_V(!p_object, StringName());
3845 
3846 	Ref<Script> script = p_object->get_script();
3847 	if (script.is_null() && p_object->is_class("Script")) {
3848 		script = p_object;
3849 	}
3850 
3851 	if (script.is_valid()) {
3852 		Ref<Script> base_script = script;
3853 		while (base_script.is_valid()) {
3854 			StringName name = EditorNode::get_editor_data().script_class_get_name(base_script->get_path());
3855 			if (name != StringName())
3856 				return name;
3857 
3858 			// should probably be deprecated in 4.x
3859 			StringName base = base_script->get_instance_base_type();
3860 			if (base != StringName() && EditorNode::get_editor_data().get_custom_types().has(base)) {
3861 				const Vector<EditorData::CustomType> &types = EditorNode::get_editor_data().get_custom_types()[base];
3862 				for (int i = 0; i < types.size(); ++i) {
3863 					if (types[i].script == base_script) {
3864 						return types[i].name;
3865 					}
3866 				}
3867 			}
3868 			base_script = base_script->get_base_script();
3869 		}
3870 	}
3871 
3872 	return StringName();
3873 }
3874 
_load_custom_class_icon(const String & p_path) const3875 Ref<ImageTexture> EditorNode::_load_custom_class_icon(const String &p_path) const {
3876 	if (p_path.length()) {
3877 		Ref<Image> img = memnew(Image);
3878 		Error err = ImageLoader::load_image(p_path, img);
3879 		if (err == OK) {
3880 			Ref<ImageTexture> icon = memnew(ImageTexture);
3881 			img->resize(16 * EDSCALE, 16 * EDSCALE, Image::INTERPOLATE_LANCZOS);
3882 			icon->create_from_image(img);
3883 			return icon;
3884 		}
3885 	}
3886 	return NULL;
3887 }
3888 
get_object_icon(const Object * p_object,const String & p_fallback) const3889 Ref<Texture> EditorNode::get_object_icon(const Object *p_object, const String &p_fallback) const {
3890 	ERR_FAIL_COND_V(!p_object || !gui_base, NULL);
3891 
3892 	Ref<Script> script = p_object->get_script();
3893 	if (script.is_null() && p_object->is_class("Script")) {
3894 		script = p_object;
3895 	}
3896 
3897 	if (script.is_valid()) {
3898 		Ref<Script> base_script = script;
3899 		while (base_script.is_valid()) {
3900 			StringName name = EditorNode::get_editor_data().script_class_get_name(base_script->get_path());
3901 			String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name);
3902 			Ref<ImageTexture> icon = _load_custom_class_icon(icon_path);
3903 			if (icon.is_valid()) {
3904 				return icon;
3905 			}
3906 
3907 			// should probably be deprecated in 4.x
3908 			StringName base = base_script->get_instance_base_type();
3909 			if (base != StringName() && EditorNode::get_editor_data().get_custom_types().has(base)) {
3910 				const Vector<EditorData::CustomType> &types = EditorNode::get_editor_data().get_custom_types()[base];
3911 				for (int i = 0; i < types.size(); ++i) {
3912 					if (types[i].script == base_script && types[i].icon.is_valid()) {
3913 						return types[i].icon;
3914 					}
3915 				}
3916 			}
3917 			base_script = base_script->get_base_script();
3918 		}
3919 	}
3920 
3921 	// should probably be deprecated in 4.x
3922 	if (p_object->has_meta("_editor_icon"))
3923 		return p_object->get_meta("_editor_icon");
3924 
3925 	if (gui_base->has_icon(p_object->get_class(), "EditorIcons"))
3926 		return gui_base->get_icon(p_object->get_class(), "EditorIcons");
3927 
3928 	if (p_fallback.length())
3929 		return gui_base->get_icon(p_fallback, "EditorIcons");
3930 
3931 	return NULL;
3932 }
3933 
get_class_icon(const String & p_class,const String & p_fallback) const3934 Ref<Texture> EditorNode::get_class_icon(const String &p_class, const String &p_fallback) const {
3935 	ERR_FAIL_COND_V_MSG(p_class.empty(), NULL, "Class name cannot be empty.");
3936 
3937 	if (ScriptServer::is_global_class(p_class)) {
3938 		Ref<ImageTexture> icon;
3939 		Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(p_class);
3940 		StringName name = p_class;
3941 
3942 		while (script.is_valid()) {
3943 			name = EditorNode::get_editor_data().script_class_get_name(script->get_path());
3944 			String current_icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name);
3945 			icon = _load_custom_class_icon(current_icon_path);
3946 			if (icon.is_valid()) {
3947 				return icon;
3948 			}
3949 			script = script->get_base_script();
3950 		}
3951 
3952 		if (icon.is_null()) {
3953 			icon = gui_base->get_icon(ScriptServer::get_global_class_base(name), "EditorIcons");
3954 		}
3955 
3956 		return icon;
3957 	}
3958 
3959 	const Map<String, Vector<EditorData::CustomType> > &p_map = EditorNode::get_editor_data().get_custom_types();
3960 	for (const Map<String, Vector<EditorData::CustomType> >::Element *E = p_map.front(); E; E = E->next()) {
3961 		const Vector<EditorData::CustomType> &ct = E->value();
3962 		for (int i = 0; i < ct.size(); ++i) {
3963 			if (ct[i].name == p_class) {
3964 				if (ct[i].icon.is_valid()) {
3965 					return ct[i].icon;
3966 				}
3967 			}
3968 		}
3969 	}
3970 
3971 	if (gui_base->has_icon(p_class, "EditorIcons")) {
3972 		return gui_base->get_icon(p_class, "EditorIcons");
3973 	}
3974 
3975 	if (p_fallback.length() && gui_base->has_icon(p_fallback, "EditorIcons")) {
3976 		return gui_base->get_icon(p_fallback, "EditorIcons");
3977 	}
3978 
3979 	return NULL;
3980 }
3981 
progress_add_task(const String & p_task,const String & p_label,int p_steps,bool p_can_cancel)3982 void EditorNode::progress_add_task(const String &p_task, const String &p_label, int p_steps, bool p_can_cancel) {
3983 
3984 	if (singleton->cmdline_export_mode) {
3985 		print_line(p_task + ": begin: " + p_label + " steps: " + itos(p_steps));
3986 	} else {
3987 		singleton->progress_dialog->add_task(p_task, p_label, p_steps, p_can_cancel);
3988 	}
3989 }
3990 
progress_task_step(const String & p_task,const String & p_state,int p_step,bool p_force_refresh)3991 bool EditorNode::progress_task_step(const String &p_task, const String &p_state, int p_step, bool p_force_refresh) {
3992 
3993 	if (singleton->cmdline_export_mode) {
3994 		print_line("\t" + p_task + ": step " + itos(p_step) + ": " + p_state);
3995 		return false;
3996 	} else {
3997 
3998 		return singleton->progress_dialog->task_step(p_task, p_state, p_step, p_force_refresh);
3999 	}
4000 }
4001 
progress_end_task(const String & p_task)4002 void EditorNode::progress_end_task(const String &p_task) {
4003 
4004 	if (singleton->cmdline_export_mode) {
4005 		print_line(p_task + ": end");
4006 	} else {
4007 		singleton->progress_dialog->end_task(p_task);
4008 	}
4009 }
4010 
progress_add_task_bg(const String & p_task,const String & p_label,int p_steps)4011 void EditorNode::progress_add_task_bg(const String &p_task, const String &p_label, int p_steps) {
4012 
4013 	singleton->progress_hb->add_task(p_task, p_label, p_steps);
4014 }
4015 
progress_task_step_bg(const String & p_task,int p_step)4016 void EditorNode::progress_task_step_bg(const String &p_task, int p_step) {
4017 
4018 	singleton->progress_hb->task_step(p_task, p_step);
4019 }
4020 
progress_end_task_bg(const String & p_task)4021 void EditorNode::progress_end_task_bg(const String &p_task) {
4022 
4023 	singleton->progress_hb->end_task(p_task);
4024 }
4025 
_file_dialog_get_icon(const String & p_path)4026 Ref<Texture> EditorNode::_file_dialog_get_icon(const String &p_path) {
4027 
4028 	EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->get_filesystem_path(p_path.get_base_dir());
4029 	if (efsd) {
4030 
4031 		String file = p_path.get_file();
4032 		for (int i = 0; i < efsd->get_file_count(); i++) {
4033 			if (efsd->get_file(i) == file) {
4034 
4035 				String type = efsd->get_file_type(i);
4036 
4037 				if (singleton->icon_type_cache.has(type)) {
4038 					return singleton->icon_type_cache[type];
4039 				} else {
4040 					return singleton->icon_type_cache["Object"];
4041 				}
4042 			}
4043 		}
4044 	}
4045 
4046 	return singleton->icon_type_cache["Object"];
4047 }
4048 
_build_icon_type_cache()4049 void EditorNode::_build_icon_type_cache() {
4050 
4051 	List<StringName> tl;
4052 	StringName ei = "EditorIcons";
4053 	theme_base->get_theme()->get_icon_list(ei, &tl);
4054 	for (List<StringName>::Element *E = tl.front(); E; E = E->next()) {
4055 
4056 		if (!ClassDB::class_exists(E->get()))
4057 			continue;
4058 		icon_type_cache[E->get()] = theme_base->get_theme()->get_icon(E->get(), ei);
4059 	}
4060 }
4061 
_file_dialog_register(FileDialog * p_dialog)4062 void EditorNode::_file_dialog_register(FileDialog *p_dialog) {
4063 
4064 	singleton->file_dialogs.insert(p_dialog);
4065 }
4066 
_file_dialog_unregister(FileDialog * p_dialog)4067 void EditorNode::_file_dialog_unregister(FileDialog *p_dialog) {
4068 
4069 	singleton->file_dialogs.erase(p_dialog);
4070 }
4071 
_editor_file_dialog_register(EditorFileDialog * p_dialog)4072 void EditorNode::_editor_file_dialog_register(EditorFileDialog *p_dialog) {
4073 
4074 	singleton->editor_file_dialogs.insert(p_dialog);
4075 }
4076 
_editor_file_dialog_unregister(EditorFileDialog * p_dialog)4077 void EditorNode::_editor_file_dialog_unregister(EditorFileDialog *p_dialog) {
4078 
4079 	singleton->editor_file_dialogs.erase(p_dialog);
4080 }
4081 
4082 Vector<EditorNodeInitCallback> EditorNode::_init_callbacks;
4083 
export_preset(const String & p_preset,const String & p_path,bool p_debug,bool p_pack_only)4084 Error EditorNode::export_preset(const String &p_preset, const String &p_path, bool p_debug, bool p_pack_only) {
4085 
4086 	export_defer.preset = p_preset;
4087 	export_defer.path = p_path;
4088 	export_defer.debug = p_debug;
4089 	export_defer.pack_only = p_pack_only;
4090 	cmdline_export_mode = true;
4091 	return OK;
4092 }
4093 
show_accept(const String & p_text,const String & p_title)4094 void EditorNode::show_accept(const String &p_text, const String &p_title) {
4095 	current_option = -1;
4096 	accept->get_ok()->set_text(p_title);
4097 	accept->set_text(p_text);
4098 	accept->popup_centered_minsize();
4099 }
4100 
show_warning(const String & p_text,const String & p_title)4101 void EditorNode::show_warning(const String &p_text, const String &p_title) {
4102 
4103 	if (warning->is_inside_tree()) {
4104 		warning->set_text(p_text);
4105 		warning->set_title(p_title);
4106 		warning->popup_centered_minsize();
4107 	} else {
4108 		WARN_PRINTS(p_title + " " + p_text);
4109 	}
4110 }
4111 
_copy_warning(const String & p_str)4112 void EditorNode::_copy_warning(const String &p_str) {
4113 
4114 	OS::get_singleton()->set_clipboard(warning->get_text());
4115 }
4116 
_dock_select_input(const Ref<InputEvent> & p_input)4117 void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) {
4118 
4119 	Ref<InputEventMouse> me = p_input;
4120 
4121 	if (me.is_valid()) {
4122 
4123 		Vector2 point = me->get_position();
4124 
4125 		int nrect = -1;
4126 		for (int i = 0; i < DOCK_SLOT_MAX; i++) {
4127 			if (dock_select_rect[i].has_point(point)) {
4128 				nrect = i;
4129 				break;
4130 			}
4131 		}
4132 
4133 		if (nrect != dock_select_rect_over) {
4134 			dock_select->update();
4135 			dock_select_rect_over = nrect;
4136 		}
4137 
4138 		if (nrect == -1)
4139 			return;
4140 
4141 		Ref<InputEventMouseButton> mb = me;
4142 
4143 		if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed() && dock_popup_selected != nrect) {
4144 			Control *dock = dock_slot[dock_popup_selected]->get_current_tab_control();
4145 			if (dock) {
4146 				dock_slot[dock_popup_selected]->remove_child(dock);
4147 			}
4148 			if (dock_slot[dock_popup_selected]->get_tab_count() == 0) {
4149 				dock_slot[dock_popup_selected]->hide();
4150 
4151 			} else {
4152 
4153 				dock_slot[dock_popup_selected]->set_current_tab(0);
4154 			}
4155 
4156 			dock_slot[nrect]->add_child(dock);
4157 			dock_popup_selected = nrect;
4158 			dock_slot[nrect]->set_current_tab(dock_slot[nrect]->get_tab_count() - 1);
4159 			dock_slot[nrect]->show();
4160 			dock_select->update();
4161 
4162 			for (int i = 0; i < vsplits.size(); i++) {
4163 				bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count();
4164 				if (in_use)
4165 					vsplits[i]->show();
4166 				else
4167 					vsplits[i]->hide();
4168 			}
4169 
4170 			if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible())
4171 				right_hsplit->show();
4172 			else
4173 				right_hsplit->hide();
4174 
4175 			_edit_current();
4176 			_save_docks();
4177 		}
4178 	}
4179 }
4180 
_dock_popup_exit()4181 void EditorNode::_dock_popup_exit() {
4182 
4183 	dock_select_rect_over = -1;
4184 	dock_select->update();
4185 }
4186 
_dock_pre_popup(int p_which)4187 void EditorNode::_dock_pre_popup(int p_which) {
4188 
4189 	dock_popup_selected = p_which;
4190 }
4191 
_dock_move_left()4192 void EditorNode::_dock_move_left() {
4193 
4194 	if (dock_popup_selected < 0 || dock_popup_selected >= DOCK_SLOT_MAX)
4195 		return;
4196 	Control *current = dock_slot[dock_popup_selected]->get_tab_control(dock_slot[dock_popup_selected]->get_current_tab());
4197 	Control *prev = dock_slot[dock_popup_selected]->get_tab_control(dock_slot[dock_popup_selected]->get_current_tab() - 1);
4198 	if (!current || !prev)
4199 		return;
4200 	dock_slot[dock_popup_selected]->move_child(current, prev->get_index());
4201 	dock_slot[dock_popup_selected]->set_current_tab(dock_slot[dock_popup_selected]->get_current_tab() - 1);
4202 	dock_select->update();
4203 	_edit_current();
4204 	_save_docks();
4205 }
4206 
_dock_move_right()4207 void EditorNode::_dock_move_right() {
4208 
4209 	Control *current = dock_slot[dock_popup_selected]->get_tab_control(dock_slot[dock_popup_selected]->get_current_tab());
4210 	Control *next = dock_slot[dock_popup_selected]->get_tab_control(dock_slot[dock_popup_selected]->get_current_tab() + 1);
4211 	if (!current || !next)
4212 		return;
4213 	dock_slot[dock_popup_selected]->move_child(next, current->get_index());
4214 	dock_slot[dock_popup_selected]->set_current_tab(dock_slot[dock_popup_selected]->get_current_tab() + 1);
4215 	dock_select->update();
4216 	_edit_current();
4217 	_save_docks();
4218 }
4219 
_dock_select_draw()4220 void EditorNode::_dock_select_draw() {
4221 	Size2 s = dock_select->get_size();
4222 	s.y /= 2.0;
4223 	s.x /= 6.0;
4224 
4225 	Color used = Color(0.6, 0.6, 0.6, 0.8);
4226 	Color used_selected = Color(0.8, 0.8, 0.8, 0.8);
4227 	Color tab_selected = theme_base->get_color("mono_color", "Editor");
4228 	Color unused = used;
4229 	unused.a = 0.4;
4230 	Color unusable = unused;
4231 	unusable.a = 0.1;
4232 
4233 	Rect2 unr(s.x * 2, 0, s.x * 2, s.y * 2);
4234 	unr.position += Vector2(2, 5);
4235 	unr.size -= Vector2(4, 7);
4236 
4237 	dock_select->draw_rect(unr, unusable);
4238 
4239 	dock_tab_move_left->set_disabled(true);
4240 	dock_tab_move_right->set_disabled(true);
4241 
4242 	if (dock_popup_selected != -1 && dock_slot[dock_popup_selected]->get_tab_count()) {
4243 
4244 		dock_tab_move_left->set_disabled(dock_slot[dock_popup_selected]->get_current_tab() == 0);
4245 		dock_tab_move_right->set_disabled(dock_slot[dock_popup_selected]->get_current_tab() >= dock_slot[dock_popup_selected]->get_tab_count() - 1);
4246 	}
4247 
4248 	for (int i = 0; i < DOCK_SLOT_MAX; i++) {
4249 
4250 		Vector2 ofs;
4251 
4252 		switch (i) {
4253 			case DOCK_SLOT_LEFT_UL: {
4254 
4255 			} break;
4256 			case DOCK_SLOT_LEFT_BL: {
4257 				ofs.y += s.y;
4258 			} break;
4259 			case DOCK_SLOT_LEFT_UR: {
4260 				ofs.x += s.x;
4261 			} break;
4262 			case DOCK_SLOT_LEFT_BR: {
4263 				ofs += s;
4264 			} break;
4265 			case DOCK_SLOT_RIGHT_UL: {
4266 				ofs.x += s.x * 4;
4267 			} break;
4268 			case DOCK_SLOT_RIGHT_BL: {
4269 				ofs.x += s.x * 4;
4270 				ofs.y += s.y;
4271 
4272 			} break;
4273 			case DOCK_SLOT_RIGHT_UR: {
4274 				ofs.x += s.x * 4;
4275 				ofs.x += s.x;
4276 
4277 			} break;
4278 			case DOCK_SLOT_RIGHT_BR: {
4279 				ofs.x += s.x * 4;
4280 				ofs += s;
4281 
4282 			} break;
4283 		}
4284 
4285 		Rect2 r(ofs, s);
4286 		dock_select_rect[i] = r;
4287 		r.position += Vector2(2, 5);
4288 		r.size -= Vector2(4, 7);
4289 
4290 		if (i == dock_select_rect_over) {
4291 			dock_select->draw_rect(r, used_selected);
4292 		} else if (dock_slot[i]->get_child_count() == 0) {
4293 			dock_select->draw_rect(r, unused);
4294 		} else {
4295 
4296 			dock_select->draw_rect(r, used);
4297 		}
4298 
4299 		for (int j = 0; j < MIN(3, dock_slot[i]->get_child_count()); j++) {
4300 			int xofs = (r.size.width / 3) * j;
4301 			Color c = used;
4302 			if (i == dock_popup_selected && (dock_slot[i]->get_current_tab() > 3 || dock_slot[i]->get_current_tab() == j))
4303 				c = tab_selected;
4304 			dock_select->draw_rect(Rect2(2 + ofs.x + xofs, ofs.y, r.size.width / 3 - 1, 3), c);
4305 		}
4306 	}
4307 }
4308 
_save_docks()4309 void EditorNode::_save_docks() {
4310 
4311 	if (waiting_for_first_scan) {
4312 		return; //scanning, do not touch docks
4313 	}
4314 	Ref<ConfigFile> config;
4315 	config.instance();
4316 
4317 	_save_docks_to_config(config, "docks");
4318 	_save_open_scenes_to_config(config, "EditorNode");
4319 	editor_data.get_plugin_window_layout(config);
4320 
4321 	config->save(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
4322 }
4323 
_save_docks_to_config(Ref<ConfigFile> p_layout,const String & p_section)4324 void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) {
4325 
4326 	for (int i = 0; i < DOCK_SLOT_MAX; i++) {
4327 		String names;
4328 		for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
4329 			String name = dock_slot[i]->get_tab_control(j)->get_name();
4330 			if (names != "")
4331 				names += ",";
4332 			names += name;
4333 		}
4334 
4335 		if (names != "") {
4336 			p_layout->set_value(p_section, "dock_" + itos(i + 1), names);
4337 		}
4338 	}
4339 
4340 	p_layout->set_value(p_section, "dock_filesystem_split", filesystem_dock->get_split_offset());
4341 	p_layout->set_value(p_section, "dock_filesystem_display_mode", filesystem_dock->get_display_mode());
4342 	p_layout->set_value(p_section, "dock_filesystem_file_list_display_mode", filesystem_dock->get_file_list_display_mode());
4343 
4344 	for (int i = 0; i < vsplits.size(); i++) {
4345 
4346 		if (vsplits[i]->is_visible_in_tree()) {
4347 			p_layout->set_value(p_section, "dock_split_" + itos(i + 1), vsplits[i]->get_split_offset());
4348 		}
4349 	}
4350 
4351 	for (int i = 0; i < hsplits.size(); i++) {
4352 
4353 		p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), hsplits[i]->get_split_offset());
4354 	}
4355 }
4356 
_save_open_scenes_to_config(Ref<ConfigFile> p_layout,const String & p_section)4357 void EditorNode::_save_open_scenes_to_config(Ref<ConfigFile> p_layout, const String &p_section) {
4358 	Array scenes;
4359 	for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
4360 		String path = editor_data.get_scene_path(i);
4361 		if (path == "") {
4362 			continue;
4363 		}
4364 		scenes.push_back(path);
4365 	}
4366 	p_layout->set_value(p_section, "open_scenes", scenes);
4367 }
4368 
save_layout()4369 void EditorNode::save_layout() {
4370 
4371 	dock_drag_timer->start();
4372 }
4373 
_dock_split_dragged(int ofs)4374 void EditorNode::_dock_split_dragged(int ofs) {
4375 
4376 	dock_drag_timer->start();
4377 }
4378 
_load_docks()4379 void EditorNode::_load_docks() {
4380 
4381 	Ref<ConfigFile> config;
4382 	config.instance();
4383 	Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
4384 	if (err != OK) {
4385 		//no config
4386 		if (overridden_default_layout >= 0) {
4387 			_layout_menu_option(overridden_default_layout);
4388 		}
4389 		return;
4390 	}
4391 
4392 	_load_docks_from_config(config, "docks");
4393 	_load_open_scenes_from_config(config, "EditorNode");
4394 
4395 	editor_data.set_plugin_window_layout(config);
4396 }
4397 
_update_dock_slots_visibility()4398 void EditorNode::_update_dock_slots_visibility() {
4399 
4400 	if (!docks_visible) {
4401 
4402 		for (int i = 0; i < DOCK_SLOT_MAX; i++) {
4403 			dock_slot[i]->hide();
4404 		}
4405 
4406 		for (int i = 0; i < vsplits.size(); i++) {
4407 			vsplits[i]->hide();
4408 		}
4409 
4410 		right_hsplit->hide();
4411 	} else {
4412 		for (int i = 0; i < DOCK_SLOT_MAX; i++) {
4413 
4414 			int tabs_visible = 0;
4415 			for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
4416 				if (!dock_slot[i]->get_tab_hidden(j)) {
4417 					tabs_visible++;
4418 				}
4419 			}
4420 			if (tabs_visible)
4421 				dock_slot[i]->show();
4422 			else
4423 				dock_slot[i]->hide();
4424 		}
4425 
4426 		for (int i = 0; i < vsplits.size(); i++) {
4427 			bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count();
4428 			if (in_use)
4429 				vsplits[i]->show();
4430 			else
4431 				vsplits[i]->hide();
4432 		}
4433 
4434 		for (int i = 0; i < DOCK_SLOT_MAX; i++) {
4435 
4436 			if (dock_slot[i]->is_visible() && dock_slot[i]->get_tab_count()) {
4437 				dock_slot[i]->set_current_tab(0);
4438 			}
4439 		}
4440 
4441 		if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible())
4442 			right_hsplit->show();
4443 		else
4444 			right_hsplit->hide();
4445 	}
4446 }
4447 
_dock_tab_changed(int p_tab)4448 void EditorNode::_dock_tab_changed(int p_tab) {
4449 
4450 	// update visibility but don't set current tab
4451 
4452 	if (!docks_visible) {
4453 
4454 		for (int i = 0; i < DOCK_SLOT_MAX; i++) {
4455 			dock_slot[i]->hide();
4456 		}
4457 
4458 		for (int i = 0; i < vsplits.size(); i++) {
4459 			vsplits[i]->hide();
4460 		}
4461 
4462 		right_hsplit->hide();
4463 		bottom_panel->hide();
4464 	} else {
4465 		for (int i = 0; i < DOCK_SLOT_MAX; i++) {
4466 
4467 			if (dock_slot[i]->get_tab_count())
4468 				dock_slot[i]->show();
4469 			else
4470 				dock_slot[i]->hide();
4471 		}
4472 
4473 		for (int i = 0; i < vsplits.size(); i++) {
4474 			bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count();
4475 			if (in_use)
4476 				vsplits[i]->show();
4477 			else
4478 				vsplits[i]->hide();
4479 		}
4480 		bottom_panel->show();
4481 
4482 		if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible())
4483 			right_hsplit->show();
4484 		else
4485 			right_hsplit->hide();
4486 	}
4487 }
4488 
_load_docks_from_config(Ref<ConfigFile> p_layout,const String & p_section)4489 void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section) {
4490 
4491 	for (int i = 0; i < DOCK_SLOT_MAX; i++) {
4492 
4493 		if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1)))
4494 			continue;
4495 
4496 		Vector<String> names = String(p_layout->get_value(p_section, "dock_" + itos(i + 1))).split(",");
4497 
4498 		for (int j = 0; j < names.size(); j++) {
4499 
4500 			String name = names[j];
4501 			//find it, in a horribly inefficient way
4502 			int atidx = -1;
4503 			Control *node = NULL;
4504 			for (int k = 0; k < DOCK_SLOT_MAX; k++) {
4505 				if (!dock_slot[k]->has_node(name))
4506 					continue;
4507 				node = Object::cast_to<Control>(dock_slot[k]->get_node(name));
4508 				if (!node)
4509 					continue;
4510 				atidx = k;
4511 				break;
4512 			}
4513 			if (atidx == -1) //well, it's not anywhere
4514 				continue;
4515 
4516 			if (atidx == i) {
4517 				node->raise();
4518 				continue;
4519 			}
4520 
4521 			dock_slot[atidx]->remove_child(node);
4522 
4523 			if (dock_slot[atidx]->get_tab_count() == 0) {
4524 				dock_slot[atidx]->hide();
4525 			}
4526 			dock_slot[i]->add_child(node);
4527 			dock_slot[i]->show();
4528 		}
4529 	}
4530 
4531 	if (p_layout->has_section_key(p_section, "dock_filesystem_split")) {
4532 		int fs_split_ofs = p_layout->get_value(p_section, "dock_filesystem_split");
4533 		filesystem_dock->set_split_offset(fs_split_ofs);
4534 	}
4535 
4536 	if (p_layout->has_section_key(p_section, "dock_filesystem_display_mode")) {
4537 		FileSystemDock::DisplayMode dock_filesystem_display_mode = FileSystemDock::DisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_display_mode")));
4538 		filesystem_dock->set_display_mode(dock_filesystem_display_mode);
4539 	}
4540 
4541 	if (p_layout->has_section_key(p_section, "dock_filesystem_file_list_display_mode")) {
4542 		FileSystemDock::FileListDisplayMode dock_filesystem_file_list_display_mode = FileSystemDock::FileListDisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_file_list_display_mode")));
4543 		filesystem_dock->set_file_list_display_mode(dock_filesystem_file_list_display_mode);
4544 	}
4545 
4546 	for (int i = 0; i < vsplits.size(); i++) {
4547 
4548 		if (!p_layout->has_section_key(p_section, "dock_split_" + itos(i + 1)))
4549 			continue;
4550 
4551 		int ofs = p_layout->get_value(p_section, "dock_split_" + itos(i + 1));
4552 		vsplits[i]->set_split_offset(ofs);
4553 	}
4554 
4555 	for (int i = 0; i < hsplits.size(); i++) {
4556 		if (!p_layout->has_section_key(p_section, "dock_hsplit_" + itos(i + 1)))
4557 			continue;
4558 		int ofs = p_layout->get_value(p_section, "dock_hsplit_" + itos(i + 1));
4559 		hsplits[i]->set_split_offset(ofs);
4560 	}
4561 
4562 	for (int i = 0; i < vsplits.size(); i++) {
4563 		bool in_use = dock_slot[i * 2 + 0]->get_tab_count() || dock_slot[i * 2 + 1]->get_tab_count();
4564 		if (in_use)
4565 			vsplits[i]->show();
4566 		else
4567 			vsplits[i]->hide();
4568 	}
4569 
4570 	if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible())
4571 		right_hsplit->show();
4572 	else
4573 		right_hsplit->hide();
4574 
4575 	for (int i = 0; i < DOCK_SLOT_MAX; i++) {
4576 
4577 		if (dock_slot[i]->is_visible() && dock_slot[i]->get_tab_count()) {
4578 			dock_slot[i]->set_current_tab(0);
4579 		}
4580 	}
4581 }
4582 
_load_open_scenes_from_config(Ref<ConfigFile> p_layout,const String & p_section)4583 void EditorNode::_load_open_scenes_from_config(Ref<ConfigFile> p_layout, const String &p_section) {
4584 	if (!bool(EDITOR_GET("interface/scene_tabs/restore_scenes_on_load"))) {
4585 		return;
4586 	}
4587 
4588 	if (!p_layout->has_section(p_section) || !p_layout->has_section_key(p_section, "open_scenes")) {
4589 		return;
4590 	}
4591 
4592 	restoring_scenes = true;
4593 
4594 	Array scenes = p_layout->get_value(p_section, "open_scenes");
4595 	for (int i = 0; i < scenes.size(); i++) {
4596 		load_scene(scenes[i]);
4597 	}
4598 	save_layout();
4599 
4600 	restoring_scenes = false;
4601 }
4602 
has_scenes_in_session()4603 bool EditorNode::has_scenes_in_session() {
4604 	if (!bool(EDITOR_GET("interface/scene_tabs/restore_scenes_on_load"))) {
4605 		return false;
4606 	}
4607 	Ref<ConfigFile> config;
4608 	config.instance();
4609 	Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
4610 	if (err != OK) {
4611 		return false;
4612 	}
4613 	if (!config->has_section("EditorNode") || !config->has_section_key("EditorNode", "open_scenes")) {
4614 		return false;
4615 	}
4616 	Array scenes = config->get_value("EditorNode", "open_scenes");
4617 	return !scenes.empty();
4618 }
4619 
ensure_main_scene(bool p_from_native)4620 bool EditorNode::ensure_main_scene(bool p_from_native) {
4621 	pick_main_scene->set_meta("from_native", p_from_native); //whether from play button or native run
4622 	String main_scene = GLOBAL_DEF("application/run/main_scene", "");
4623 
4624 	if (main_scene == "") {
4625 
4626 		current_option = -1;
4627 		pick_main_scene->set_text(TTR("No main scene has ever been defined, select one?\nYou can change it later in \"Project Settings\" under the 'application' category."));
4628 		pick_main_scene->popup_centered_minsize();
4629 		return false;
4630 	}
4631 
4632 	if (!FileAccess::exists(main_scene)) {
4633 
4634 		current_option = -1;
4635 		pick_main_scene->set_text(vformat(TTR("Selected scene '%s' does not exist, select a valid one?\nYou can change it later in \"Project Settings\" under the 'application' category."), main_scene));
4636 		pick_main_scene->popup_centered_minsize();
4637 		return false;
4638 	}
4639 
4640 	if (ResourceLoader::get_resource_type(main_scene) != "PackedScene") {
4641 
4642 		current_option = -1;
4643 		pick_main_scene->set_text(vformat(TTR("Selected scene '%s' is not a scene file, select a valid one?\nYou can change it later in \"Project Settings\" under the 'application' category."), main_scene));
4644 		pick_main_scene->popup_centered_minsize();
4645 		return false;
4646 	}
4647 
4648 	return true;
4649 }
4650 
run_play()4651 void EditorNode::run_play() {
4652 	_menu_option_confirm(RUN_STOP, true);
4653 	_run(false);
4654 }
4655 
run_play_current()4656 void EditorNode::run_play_current() {
4657 	_save_default_environment();
4658 	_menu_option_confirm(RUN_STOP, true);
4659 	_run(true);
4660 }
4661 
run_play_custom(const String & p_custom)4662 void EditorNode::run_play_custom(const String &p_custom) {
4663 	_menu_option_confirm(RUN_STOP, true);
4664 	_run(false, p_custom);
4665 }
4666 
run_stop()4667 void EditorNode::run_stop() {
4668 	_menu_option_confirm(RUN_STOP, false);
4669 }
4670 
is_run_playing() const4671 bool EditorNode::is_run_playing() const {
4672 	EditorRun::Status status = editor_run.get_status();
4673 	return (status == EditorRun::STATUS_PLAY || status == EditorRun::STATUS_PAUSED);
4674 }
4675 
get_run_playing_scene() const4676 String EditorNode::get_run_playing_scene() const {
4677 	String run_filename = editor_run.get_running_scene();
4678 	if (run_filename == "" && is_run_playing()) {
4679 		run_filename = GLOBAL_DEF("application/run/main_scene", ""); // Must be the main scene then.
4680 	}
4681 
4682 	return run_filename;
4683 }
4684 
get_current_tab()4685 int EditorNode::get_current_tab() {
4686 	return scene_tabs->get_current_tab();
4687 }
4688 
set_current_tab(int p_tab)4689 void EditorNode::set_current_tab(int p_tab) {
4690 	scene_tabs->set_current_tab(p_tab);
4691 }
4692 
_update_layouts_menu()4693 void EditorNode::_update_layouts_menu() {
4694 
4695 	editor_layouts->clear();
4696 	overridden_default_layout = -1;
4697 
4698 	editor_layouts->set_size(Vector2());
4699 	editor_layouts->add_shortcut(ED_SHORTCUT("layout/save", TTR("Save Layout")), SETTINGS_LAYOUT_SAVE);
4700 	editor_layouts->add_shortcut(ED_SHORTCUT("layout/delete", TTR("Delete Layout")), SETTINGS_LAYOUT_DELETE);
4701 	editor_layouts->add_separator();
4702 	editor_layouts->add_shortcut(ED_SHORTCUT("layout/default", TTR("Default")), SETTINGS_LAYOUT_DEFAULT);
4703 
4704 	Ref<ConfigFile> config;
4705 	config.instance();
4706 	Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
4707 	if (err != OK) {
4708 		return; //no config
4709 	}
4710 
4711 	List<String> layouts;
4712 	config.ptr()->get_sections(&layouts);
4713 
4714 	for (List<String>::Element *E = layouts.front(); E; E = E->next()) {
4715 
4716 		String layout = E->get();
4717 
4718 		if (layout == TTR("Default")) {
4719 			editor_layouts->remove_item(editor_layouts->get_item_index(SETTINGS_LAYOUT_DEFAULT));
4720 			overridden_default_layout = editor_layouts->get_item_count();
4721 		}
4722 
4723 		editor_layouts->add_item(layout);
4724 	}
4725 }
4726 
_layout_menu_option(int p_id)4727 void EditorNode::_layout_menu_option(int p_id) {
4728 
4729 	switch (p_id) {
4730 
4731 		case SETTINGS_LAYOUT_SAVE: {
4732 
4733 			current_option = p_id;
4734 			layout_dialog->set_title(TTR("Save Layout"));
4735 			layout_dialog->get_ok()->set_text(TTR("Save"));
4736 			layout_dialog->popup_centered();
4737 			layout_dialog->set_name_line_enabled(true);
4738 		} break;
4739 		case SETTINGS_LAYOUT_DELETE: {
4740 
4741 			current_option = p_id;
4742 			layout_dialog->set_title(TTR("Delete Layout"));
4743 			layout_dialog->get_ok()->set_text(TTR("Delete"));
4744 			layout_dialog->popup_centered();
4745 			layout_dialog->set_name_line_enabled(false);
4746 		} break;
4747 		case SETTINGS_LAYOUT_DEFAULT: {
4748 
4749 			_load_docks_from_config(default_layout, "docks");
4750 			_save_docks();
4751 		} break;
4752 		default: {
4753 
4754 			Ref<ConfigFile> config;
4755 			config.instance();
4756 			Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
4757 			if (err != OK) {
4758 				return; //no config
4759 			}
4760 
4761 			_load_docks_from_config(config, editor_layouts->get_item_text(p_id));
4762 			_save_docks();
4763 		}
4764 	}
4765 }
4766 
_scene_tab_script_edited(int p_tab)4767 void EditorNode::_scene_tab_script_edited(int p_tab) {
4768 
4769 	Ref<Script> script = editor_data.get_scene_root_script(p_tab);
4770 	if (script.is_valid())
4771 		inspector_dock->edit_resource(script);
4772 }
4773 
_scene_tab_closed(int p_tab,int option)4774 void EditorNode::_scene_tab_closed(int p_tab, int option) {
4775 	current_option = option;
4776 	tab_closing = p_tab;
4777 	Node *scene = editor_data.get_edited_scene_root(p_tab);
4778 	if (!scene) {
4779 		_discard_changes();
4780 		return;
4781 	}
4782 
4783 	bool unsaved = (p_tab == editor_data.get_edited_scene()) ?
4784 						   saved_version != editor_data.get_undo_redo().get_version() :
4785 						   editor_data.get_scene_version(p_tab) != 0;
4786 	if (unsaved) {
4787 		save_confirmation->get_ok()->set_text(TTR("Save & Close"));
4788 		save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene->get_filename() != "" ? scene->get_filename() : "unsaved scene"));
4789 		save_confirmation->popup_centered_minsize();
4790 	} else {
4791 		_discard_changes();
4792 	}
4793 
4794 	save_layout();
4795 	_update_scene_tabs();
4796 }
4797 
_scene_tab_hover(int p_tab)4798 void EditorNode::_scene_tab_hover(int p_tab) {
4799 	if (!bool(EDITOR_GET("interface/scene_tabs/show_thumbnail_on_hover"))) {
4800 		return;
4801 	}
4802 	int current_tab = scene_tabs->get_current_tab();
4803 
4804 	if (p_tab == current_tab || p_tab < 0) {
4805 		tab_preview_panel->hide();
4806 	} else {
4807 		String path = editor_data.get_scene_path(p_tab);
4808 		if (path != String()) {
4809 			EditorResourcePreview::get_singleton()->queue_resource_preview(path, this, "_thumbnail_done", p_tab);
4810 		}
4811 	}
4812 }
4813 
_scene_tab_exit()4814 void EditorNode::_scene_tab_exit() {
4815 	tab_preview_panel->hide();
4816 }
4817 
_scene_tab_input(const Ref<InputEvent> & p_input)4818 void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) {
4819 	Ref<InputEventMouseButton> mb = p_input;
4820 
4821 	if (mb.is_valid()) {
4822 
4823 		if (scene_tabs->get_hovered_tab() >= 0) {
4824 			if (mb->get_button_index() == BUTTON_MIDDLE && mb->is_pressed()) {
4825 				_scene_tab_closed(scene_tabs->get_hovered_tab());
4826 			}
4827 		} else {
4828 			if ((mb->get_button_index() == BUTTON_LEFT && mb->is_doubleclick()) || (mb->get_button_index() == BUTTON_MIDDLE && mb->is_pressed())) {
4829 				_menu_option_confirm(FILE_NEW_SCENE, true);
4830 			}
4831 		}
4832 		if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
4833 
4834 			// context menu
4835 			scene_tabs_context_menu->clear();
4836 			scene_tabs_context_menu->set_size(Size2(1, 1));
4837 
4838 			scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/new_scene"), FILE_NEW_SCENE);
4839 			if (scene_tabs->get_hovered_tab() >= 0) {
4840 				scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene"), FILE_SAVE_SCENE);
4841 				scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene_as"), FILE_SAVE_AS_SCENE);
4842 			}
4843 			scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_all_scenes"), FILE_SAVE_ALL_SCENES);
4844 			if (scene_tabs->get_hovered_tab() >= 0) {
4845 				scene_tabs_context_menu->add_separator();
4846 				scene_tabs_context_menu->add_item(TTR("Show in FileSystem"), FILE_SHOW_IN_FILESYSTEM);
4847 				scene_tabs_context_menu->add_item(TTR("Play This Scene"), RUN_PLAY_SCENE);
4848 
4849 				scene_tabs_context_menu->add_separator();
4850 				Ref<ShortCut> close_tab_sc = ED_GET_SHORTCUT("editor/close_scene");
4851 				close_tab_sc->set_name(TTR("Close Tab"));
4852 				scene_tabs_context_menu->add_shortcut(close_tab_sc, FILE_CLOSE);
4853 				Ref<ShortCut> undo_close_tab_sc = ED_GET_SHORTCUT("editor/reopen_closed_scene");
4854 				undo_close_tab_sc->set_name(TTR("Undo Close Tab"));
4855 				scene_tabs_context_menu->add_shortcut(undo_close_tab_sc, FILE_OPEN_PREV);
4856 				if (previous_scenes.empty()) {
4857 					scene_tabs_context_menu->set_item_disabled(scene_tabs_context_menu->get_item_index(FILE_OPEN_PREV), true);
4858 				}
4859 				scene_tabs_context_menu->add_item(TTR("Close Other Tabs"), FILE_CLOSE_OTHERS);
4860 				scene_tabs_context_menu->add_item(TTR("Close Tabs to the Right"), FILE_CLOSE_RIGHT);
4861 				scene_tabs_context_menu->add_item(TTR("Close All Tabs"), FILE_CLOSE_ALL);
4862 			}
4863 			scene_tabs_context_menu->set_position(mb->get_global_position());
4864 			scene_tabs_context_menu->popup();
4865 		}
4866 	}
4867 }
4868 
_reposition_active_tab(int idx_to)4869 void EditorNode::_reposition_active_tab(int idx_to) {
4870 	editor_data.move_edited_scene_to_index(idx_to);
4871 	_update_scene_tabs();
4872 }
4873 
_thumbnail_done(const String & p_path,const Ref<Texture> & p_preview,const Ref<Texture> & p_small_preview,const Variant & p_udata)4874 void EditorNode::_thumbnail_done(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, const Variant &p_udata) {
4875 	int p_tab = p_udata.operator signed int();
4876 	if (p_preview.is_valid()) {
4877 		Rect2 rect = scene_tabs->get_tab_rect(p_tab);
4878 		rect.position += scene_tabs->get_global_position();
4879 		tab_preview->set_texture(p_preview);
4880 		tab_preview_panel->set_position(rect.position + Vector2(0, rect.size.height));
4881 		tab_preview_panel->show();
4882 	}
4883 }
4884 
_scene_tab_changed(int p_tab)4885 void EditorNode::_scene_tab_changed(int p_tab) {
4886 	tab_preview_panel->hide();
4887 
4888 	bool unsaved = (saved_version != editor_data.get_undo_redo().get_version());
4889 
4890 	if (p_tab == editor_data.get_edited_scene())
4891 		return; //pointless
4892 
4893 	uint64_t next_scene_version = editor_data.get_scene_version(p_tab);
4894 
4895 	editor_data.get_undo_redo().create_action(TTR("Switch Scene Tab"));
4896 	editor_data.get_undo_redo().add_do_method(this, "set_current_version", unsaved ? saved_version : 0);
4897 	editor_data.get_undo_redo().add_do_method(this, "set_current_scene", p_tab);
4898 	editor_data.get_undo_redo().add_do_method(this, "set_current_version", next_scene_version == 0 ? editor_data.get_undo_redo().get_version() + 1 : next_scene_version);
4899 
4900 	editor_data.get_undo_redo().add_undo_method(this, "set_current_version", next_scene_version);
4901 	editor_data.get_undo_redo().add_undo_method(this, "set_current_scene", editor_data.get_edited_scene());
4902 	editor_data.get_undo_redo().add_undo_method(this, "set_current_version", saved_version);
4903 	editor_data.get_undo_redo().commit_action();
4904 }
4905 
add_bottom_panel_item(String p_text,Control * p_item)4906 ToolButton *EditorNode::add_bottom_panel_item(String p_text, Control *p_item) {
4907 
4908 	ToolButton *tb = memnew(ToolButton);
4909 	tb->connect("toggled", this, "_bottom_panel_switch", varray(bottom_panel_items.size()));
4910 	tb->set_text(p_text);
4911 	tb->set_toggle_mode(true);
4912 	tb->set_focus_mode(Control::FOCUS_NONE);
4913 	bottom_panel_vb->add_child(p_item);
4914 	bottom_panel_hb->raise();
4915 	bottom_panel_hb_editors->add_child(tb);
4916 	p_item->set_v_size_flags(Control::SIZE_EXPAND_FILL);
4917 	p_item->hide();
4918 	BottomPanelItem bpi;
4919 	bpi.button = tb;
4920 	bpi.control = p_item;
4921 	bpi.name = p_text;
4922 	bottom_panel_items.push_back(bpi);
4923 
4924 	return tb;
4925 }
4926 
are_bottom_panels_hidden() const4927 bool EditorNode::are_bottom_panels_hidden() const {
4928 
4929 	for (int i = 0; i < bottom_panel_items.size(); i++) {
4930 		if (bottom_panel_items[i].button->is_pressed())
4931 			return false;
4932 	}
4933 
4934 	return true;
4935 }
4936 
hide_bottom_panel()4937 void EditorNode::hide_bottom_panel() {
4938 
4939 	for (int i = 0; i < bottom_panel_items.size(); i++) {
4940 
4941 		if (bottom_panel_items[i].control->is_visible()) {
4942 			_bottom_panel_switch(false, i);
4943 			break;
4944 		}
4945 	}
4946 }
4947 
make_bottom_panel_item_visible(Control * p_item)4948 void EditorNode::make_bottom_panel_item_visible(Control *p_item) {
4949 
4950 	for (int i = 0; i < bottom_panel_items.size(); i++) {
4951 
4952 		if (bottom_panel_items[i].control == p_item) {
4953 			_bottom_panel_switch(true, i);
4954 			break;
4955 		}
4956 	}
4957 }
4958 
raise_bottom_panel_item(Control * p_item)4959 void EditorNode::raise_bottom_panel_item(Control *p_item) {
4960 
4961 	for (int i = 0; i < bottom_panel_items.size(); i++) {
4962 
4963 		if (bottom_panel_items[i].control == p_item) {
4964 			bottom_panel_items[i].button->raise();
4965 			SWAP(bottom_panel_items.write[i], bottom_panel_items.write[bottom_panel_items.size() - 1]);
4966 			break;
4967 		}
4968 	}
4969 
4970 	for (int i = 0; i < bottom_panel_items.size(); i++) {
4971 		bottom_panel_items[i].button->disconnect("toggled", this, "_bottom_panel_switch");
4972 		bottom_panel_items[i].button->connect("toggled", this, "_bottom_panel_switch", varray(i));
4973 	}
4974 }
4975 
remove_bottom_panel_item(Control * p_item)4976 void EditorNode::remove_bottom_panel_item(Control *p_item) {
4977 
4978 	for (int i = 0; i < bottom_panel_items.size(); i++) {
4979 
4980 		if (bottom_panel_items[i].control == p_item) {
4981 			if (p_item->is_visible_in_tree()) {
4982 				_bottom_panel_switch(false, i);
4983 			}
4984 			bottom_panel_vb->remove_child(bottom_panel_items[i].control);
4985 			bottom_panel_hb_editors->remove_child(bottom_panel_items[i].button);
4986 			memdelete(bottom_panel_items[i].button);
4987 			bottom_panel_items.remove(i);
4988 			break;
4989 		}
4990 	}
4991 
4992 	for (int i = 0; i < bottom_panel_items.size(); i++) {
4993 		bottom_panel_items[i].button->disconnect("toggled", this, "_bottom_panel_switch");
4994 		bottom_panel_items[i].button->connect("toggled", this, "_bottom_panel_switch", varray(i));
4995 	}
4996 }
4997 
_bottom_panel_switch(bool p_enable,int p_idx)4998 void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) {
4999 
5000 	ERR_FAIL_INDEX(p_idx, bottom_panel_items.size());
5001 
5002 	if (bottom_panel_items[p_idx].control->is_visible() == p_enable) {
5003 		return;
5004 	}
5005 
5006 	if (p_enable) {
5007 		for (int i = 0; i < bottom_panel_items.size(); i++) {
5008 
5009 			bottom_panel_items[i].button->set_pressed(i == p_idx);
5010 			bottom_panel_items[i].control->set_visible(i == p_idx);
5011 		}
5012 		if (ScriptEditor::get_singleton()->get_debugger() == bottom_panel_items[p_idx].control) { // this is the debug panel which uses tabs, so the top section should be smaller
5013 			bottom_panel->add_style_override("panel", gui_base->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles"));
5014 		} else {
5015 			bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer"));
5016 		}
5017 		center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE);
5018 		center_split->set_collapsed(false);
5019 		if (bottom_panel_raise->is_pressed()) {
5020 			top_split->hide();
5021 		}
5022 		bottom_panel_raise->show();
5023 
5024 	} else {
5025 		bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer"));
5026 		bottom_panel_items[p_idx].button->set_pressed(false);
5027 		bottom_panel_items[p_idx].control->set_visible(false);
5028 		center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);
5029 		center_split->set_collapsed(true);
5030 		bottom_panel_raise->hide();
5031 		if (bottom_panel_raise->is_pressed()) {
5032 			top_split->show();
5033 		}
5034 	}
5035 }
5036 
set_docks_visible(bool p_show)5037 void EditorNode::set_docks_visible(bool p_show) {
5038 	docks_visible = p_show;
5039 	_update_dock_slots_visibility();
5040 }
5041 
get_docks_visible() const5042 bool EditorNode::get_docks_visible() const {
5043 	return docks_visible;
5044 }
5045 
_toggle_distraction_free_mode()5046 void EditorNode::_toggle_distraction_free_mode() {
5047 
5048 	if (EditorSettings::get_singleton()->get("interface/editor/separate_distraction_mode")) {
5049 		int screen = -1;
5050 		for (int i = 0; i < editor_table.size(); i++) {
5051 			if (editor_plugin_screen == editor_table[i]) {
5052 				screen = i;
5053 				break;
5054 			}
5055 		}
5056 
5057 		if (screen == EDITOR_SCRIPT) {
5058 			script_distraction = !script_distraction;
5059 			set_distraction_free_mode(script_distraction);
5060 		} else {
5061 			scene_distraction = !scene_distraction;
5062 			set_distraction_free_mode(scene_distraction);
5063 		}
5064 	} else {
5065 		set_distraction_free_mode(distraction_free->is_pressed());
5066 	}
5067 }
5068 
set_distraction_free_mode(bool p_enter)5069 void EditorNode::set_distraction_free_mode(bool p_enter) {
5070 
5071 	distraction_free->set_pressed(p_enter);
5072 
5073 	if (p_enter) {
5074 		if (docks_visible) {
5075 			set_docks_visible(false);
5076 		}
5077 	} else {
5078 		set_docks_visible(true);
5079 	}
5080 }
5081 
is_distraction_free_mode_enabled() const5082 bool EditorNode::is_distraction_free_mode_enabled() const {
5083 	return distraction_free->is_pressed();
5084 }
5085 
add_control_to_dock(DockSlot p_slot,Control * p_control)5086 void EditorNode::add_control_to_dock(DockSlot p_slot, Control *p_control) {
5087 	ERR_FAIL_INDEX(p_slot, DOCK_SLOT_MAX);
5088 	dock_slot[p_slot]->add_child(p_control);
5089 	_update_dock_slots_visibility();
5090 }
5091 
remove_control_from_dock(Control * p_control)5092 void EditorNode::remove_control_from_dock(Control *p_control) {
5093 
5094 	Control *dock = NULL;
5095 	for (int i = 0; i < DOCK_SLOT_MAX; i++) {
5096 		if (p_control->get_parent() == dock_slot[i]) {
5097 			dock = dock_slot[i];
5098 			break;
5099 		}
5100 	}
5101 
5102 	ERR_FAIL_COND_MSG(!dock, "Control was not in dock.");
5103 
5104 	dock->remove_child(p_control);
5105 	_update_dock_slots_visibility();
5106 }
5107 
drag_resource(const Ref<Resource> & p_res,Control * p_from)5108 Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) {
5109 
5110 	Control *drag_control = memnew(Control);
5111 	TextureRect *drag_preview = memnew(TextureRect);
5112 	Label *label = memnew(Label);
5113 
5114 	Ref<Texture> preview;
5115 
5116 	{
5117 		//todo make proper previews
5118 		Ref<ImageTexture> pic = gui_base->get_icon("FileBigThumb", "EditorIcons");
5119 		Ref<Image> img = pic->get_data();
5120 		img = img->duplicate();
5121 		img->resize(48, 48); //meh
5122 		Ref<ImageTexture> resized_pic = Ref<ImageTexture>(memnew(ImageTexture));
5123 		resized_pic->create_from_image(img);
5124 		preview = resized_pic;
5125 	}
5126 
5127 	drag_preview->set_texture(preview);
5128 	drag_control->add_child(drag_preview);
5129 	if (p_res->get_path().is_resource_file()) {
5130 		label->set_text(p_res->get_path().get_file());
5131 	} else if (p_res->get_name() != "") {
5132 		label->set_text(p_res->get_name());
5133 	} else {
5134 		label->set_text(p_res->get_class());
5135 	}
5136 
5137 	drag_control->add_child(label);
5138 
5139 	p_from->set_drag_preview(drag_control); //wait until it enters scene
5140 
5141 	label->set_position(Point2((preview->get_width() - label->get_minimum_size().width) / 2, preview->get_height()));
5142 
5143 	Dictionary drag_data;
5144 	drag_data["type"] = "resource";
5145 	drag_data["resource"] = p_res;
5146 	drag_data["from"] = p_from;
5147 
5148 	return drag_data;
5149 }
5150 
drag_files_and_dirs(const Vector<String> & p_paths,Control * p_from)5151 Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control *p_from) {
5152 	bool has_folder = false;
5153 	bool has_file = false;
5154 	for (int i = 0; i < p_paths.size(); i++) {
5155 		bool is_folder = p_paths[i].ends_with("/");
5156 		has_folder |= is_folder;
5157 		has_file |= !is_folder;
5158 	}
5159 
5160 	int max_rows = 6;
5161 	int num_rows = p_paths.size() > max_rows ? max_rows - 1 : p_paths.size(); // Don't waste a row to say "1 more file" - list it instead.
5162 	VBoxContainer *vbox = memnew(VBoxContainer);
5163 	for (int i = 0; i < num_rows; i++) {
5164 		HBoxContainer *hbox = memnew(HBoxContainer);
5165 		TextureRect *icon = memnew(TextureRect);
5166 		Label *label = memnew(Label);
5167 
5168 		if (p_paths[i].ends_with("/")) {
5169 			label->set_text(p_paths[i].substr(0, p_paths[i].length() - 1).get_file());
5170 			icon->set_texture(gui_base->get_icon("Folder", "EditorIcons"));
5171 		} else {
5172 			label->set_text(p_paths[i].get_file());
5173 			icon->set_texture(gui_base->get_icon("File", "EditorIcons"));
5174 		}
5175 		icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
5176 		icon->set_size(Size2(16, 16));
5177 		hbox->add_child(icon);
5178 		hbox->add_child(label);
5179 		vbox->add_child(hbox);
5180 	}
5181 
5182 	if (p_paths.size() > num_rows) {
5183 		Label *label = memnew(Label);
5184 		if (has_file && has_folder) {
5185 			label->set_text(vformat(TTR("%d more files or folders"), p_paths.size() - num_rows));
5186 		} else if (has_folder) {
5187 			label->set_text(vformat(TTR("%d more folders"), p_paths.size() - num_rows));
5188 		} else {
5189 			label->set_text(vformat(TTR("%d more files"), p_paths.size() - num_rows));
5190 		}
5191 		vbox->add_child(label);
5192 	}
5193 	p_from->set_drag_preview(vbox); //wait until it enters scene
5194 
5195 	Dictionary drag_data;
5196 	drag_data["type"] = has_folder ? "files_and_dirs" : "files";
5197 	drag_data["files"] = p_paths;
5198 	drag_data["from"] = p_from;
5199 	return drag_data;
5200 }
5201 
add_tool_menu_item(const String & p_name,Object * p_handler,const String & p_callback,const Variant & p_ud)5202 void EditorNode::add_tool_menu_item(const String &p_name, Object *p_handler, const String &p_callback, const Variant &p_ud) {
5203 	ERR_FAIL_NULL(p_handler);
5204 	int idx = tool_menu->get_item_count();
5205 	tool_menu->add_item(p_name, TOOLS_CUSTOM);
5206 
5207 	Array parameters;
5208 	parameters.push_back(p_handler->get_instance_id());
5209 	parameters.push_back(p_callback);
5210 	parameters.push_back(p_ud);
5211 
5212 	tool_menu->set_item_metadata(idx, parameters);
5213 }
5214 
add_tool_submenu_item(const String & p_name,PopupMenu * p_submenu)5215 void EditorNode::add_tool_submenu_item(const String &p_name, PopupMenu *p_submenu) {
5216 	ERR_FAIL_NULL(p_submenu);
5217 	ERR_FAIL_COND(p_submenu->get_parent() != NULL);
5218 
5219 	tool_menu->add_child(p_submenu);
5220 	tool_menu->add_submenu_item(p_name, p_submenu->get_name(), TOOLS_CUSTOM);
5221 }
5222 
remove_tool_menu_item(const String & p_name)5223 void EditorNode::remove_tool_menu_item(const String &p_name) {
5224 	for (int i = 0; i < tool_menu->get_item_count(); i++) {
5225 		if (tool_menu->get_item_id(i) != TOOLS_CUSTOM)
5226 			continue;
5227 
5228 		if (tool_menu->get_item_text(i) == p_name) {
5229 			if (tool_menu->get_item_submenu(i) != "") {
5230 				Node *n = tool_menu->get_node(tool_menu->get_item_submenu(i));
5231 				tool_menu->remove_child(n);
5232 				memdelete(n);
5233 			}
5234 			tool_menu->remove_item(i);
5235 			tool_menu->set_as_minsize();
5236 			return;
5237 		}
5238 	}
5239 }
5240 
_global_menu_action(const Variant & p_id,const Variant & p_meta)5241 void EditorNode::_global_menu_action(const Variant &p_id, const Variant &p_meta) {
5242 
5243 	int id = (int)p_id;
5244 	if (id == GLOBAL_NEW_WINDOW) {
5245 		if (OS::get_singleton()->get_main_loop()) {
5246 			List<String> args;
5247 			args.push_back("-e");
5248 			String exec = OS::get_singleton()->get_executable_path();
5249 
5250 			OS::ProcessID pid = 0;
5251 			OS::get_singleton()->execute(exec, args, false, &pid);
5252 		}
5253 	} else if (id == GLOBAL_SCENE) {
5254 		int idx = (int)p_meta;
5255 		scene_tabs->set_current_tab(idx);
5256 	}
5257 }
5258 
_dropped_files(const Vector<String> & p_files,int p_screen)5259 void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) {
5260 
5261 	String to_path = ProjectSettings::get_singleton()->globalize_path(get_filesystem_dock()->get_selected_path());
5262 
5263 	_add_dropped_files_recursive(p_files, to_path);
5264 
5265 	EditorFileSystem::get_singleton()->scan_changes();
5266 }
5267 
_add_dropped_files_recursive(const Vector<String> & p_files,String to_path)5268 void EditorNode::_add_dropped_files_recursive(const Vector<String> &p_files, String to_path) {
5269 
5270 	DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
5271 	Vector<String> just_copy = String("ttf,otf").split(",");
5272 
5273 	for (int i = 0; i < p_files.size(); i++) {
5274 
5275 		String from = p_files[i];
5276 		String to = to_path.plus_file(from.get_file());
5277 
5278 		if (dir->dir_exists(from)) {
5279 
5280 			Vector<String> sub_files;
5281 
5282 			DirAccessRef sub_dir = DirAccess::open(from);
5283 			sub_dir->list_dir_begin();
5284 
5285 			String next_file = sub_dir->get_next();
5286 			while (next_file != "") {
5287 				if (next_file == "." || next_file == "..") {
5288 					next_file = sub_dir->get_next();
5289 					continue;
5290 				}
5291 
5292 				sub_files.push_back(from.plus_file(next_file));
5293 				next_file = sub_dir->get_next();
5294 			}
5295 
5296 			if (!sub_files.empty()) {
5297 				dir->make_dir(to);
5298 				_add_dropped_files_recursive(sub_files, to);
5299 			}
5300 
5301 			continue;
5302 		}
5303 
5304 		if (!ResourceFormatImporter::get_singleton()->can_be_imported(from) && (just_copy.find(from.get_extension().to_lower()) == -1)) {
5305 			continue;
5306 		}
5307 		dir->copy(from, to);
5308 	}
5309 }
5310 
_file_access_close_error_notify(const String & p_str)5311 void EditorNode::_file_access_close_error_notify(const String &p_str) {
5312 
5313 	add_io_error("Unable to write to file '" + p_str + "', file in use, locked or lacking permissions.");
5314 }
5315 
reload_scene(const String & p_path)5316 void EditorNode::reload_scene(const String &p_path) {
5317 
5318 	//first of all, reload internal textures, materials, meshes, etc. as they might have changed on disk
5319 
5320 	List<Ref<Resource> > cached;
5321 	ResourceCache::get_cached_resources(&cached);
5322 	List<Ref<Resource> > to_clear; //clear internal resources from previous scene from being used
5323 	for (List<Ref<Resource> >::Element *E = cached.front(); E; E = E->next()) {
5324 
5325 		if (E->get()->get_path().begins_with(p_path + "::")) { //subresources of existing scene
5326 			to_clear.push_back(E->get());
5327 		}
5328 	}
5329 
5330 	//so reload reloads everything, clear subresources of previous scene
5331 	while (to_clear.front()) {
5332 		to_clear.front()->get()->set_path("");
5333 		to_clear.pop_front();
5334 	}
5335 
5336 	int scene_idx = -1;
5337 	for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
5338 
5339 		if (editor_data.get_scene_path(i) == p_path) {
5340 			scene_idx = i;
5341 			break;
5342 		}
5343 	}
5344 
5345 	int current_tab = editor_data.get_edited_scene();
5346 
5347 	if (scene_idx == -1) {
5348 		if (get_edited_scene()) {
5349 			//scene is not open, so at it might be instanced. We'll refresh the whole scene later.
5350 			editor_data.get_undo_redo().clear_history();
5351 		}
5352 		return;
5353 	}
5354 
5355 	if (current_tab == scene_idx) {
5356 		editor_data.apply_changes_in_editors();
5357 		_set_scene_metadata(p_path);
5358 	}
5359 
5360 	//remove scene
5361 	_remove_scene(scene_idx, false);
5362 
5363 	//reload scene
5364 	load_scene(p_path, true, false, true, true);
5365 
5366 	//adjust index so tab is back a the previous position
5367 	editor_data.move_edited_scene_to_index(scene_idx);
5368 	get_undo_redo()->clear_history();
5369 
5370 	//recover the tab
5371 	scene_tabs->set_current_tab(current_tab);
5372 }
5373 
5374 int EditorNode::plugin_init_callback_count = 0;
5375 
add_plugin_init_callback(EditorPluginInitializeCallback p_callback)5376 void EditorNode::add_plugin_init_callback(EditorPluginInitializeCallback p_callback) {
5377 
5378 	ERR_FAIL_COND(plugin_init_callback_count == MAX_INIT_CALLBACKS);
5379 
5380 	plugin_init_callbacks[plugin_init_callback_count++] = p_callback;
5381 }
5382 
5383 EditorPluginInitializeCallback EditorNode::plugin_init_callbacks[EditorNode::MAX_INIT_CALLBACKS];
5384 
5385 int EditorNode::build_callback_count = 0;
5386 
add_build_callback(EditorBuildCallback p_callback)5387 void EditorNode::add_build_callback(EditorBuildCallback p_callback) {
5388 
5389 	ERR_FAIL_COND(build_callback_count == MAX_INIT_CALLBACKS);
5390 
5391 	build_callbacks[build_callback_count++] = p_callback;
5392 }
5393 
5394 EditorBuildCallback EditorNode::build_callbacks[EditorNode::MAX_BUILD_CALLBACKS];
5395 
call_build()5396 bool EditorNode::call_build() {
5397 
5398 	bool builds_successful = true;
5399 
5400 	for (int i = 0; i < build_callback_count && builds_successful; i++) {
5401 		if (!build_callbacks[i]()) {
5402 			ERR_PRINT("A Godot Engine build callback failed.");
5403 			builds_successful = false;
5404 		}
5405 	}
5406 
5407 	if (builds_successful && !editor_data.call_build()) {
5408 		ERR_PRINT("An EditorPlugin build callback failed.");
5409 		builds_successful = false;
5410 	}
5411 
5412 	return builds_successful;
5413 }
5414 
_inherit_imported(const String & p_action)5415 void EditorNode::_inherit_imported(const String &p_action) {
5416 
5417 	open_imported->hide();
5418 	load_scene(open_import_request, true, true);
5419 }
5420 
_open_imported()5421 void EditorNode::_open_imported() {
5422 
5423 	load_scene(open_import_request, true, false, true, true);
5424 }
5425 
dim_editor(bool p_dimming,bool p_force_dim)5426 void EditorNode::dim_editor(bool p_dimming, bool p_force_dim) {
5427 	// Dimming can be forced regardless of the editor setting, which is useful when quitting the editor.
5428 	if ((p_force_dim || EditorSettings::get_singleton()->get("interface/editor/dim_editor_on_dialog_popup")) && p_dimming) {
5429 		dimmed = true;
5430 		gui_base->set_modulate(Color(0.5, 0.5, 0.5));
5431 	} else {
5432 		dimmed = false;
5433 		gui_base->set_modulate(Color(1, 1, 1));
5434 	}
5435 }
5436 
is_editor_dimmed() const5437 bool EditorNode::is_editor_dimmed() const {
5438 	return dimmed;
5439 }
5440 
open_export_template_manager()5441 void EditorNode::open_export_template_manager() {
5442 
5443 	export_template_manager->popup_manager();
5444 }
5445 
add_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> & p_plugin)5446 void EditorNode::add_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin) {
5447 	resource_conversion_plugins.push_back(p_plugin);
5448 }
5449 
remove_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> & p_plugin)5450 void EditorNode::remove_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin) {
5451 	resource_conversion_plugins.erase(p_plugin);
5452 }
5453 
find_resource_conversion_plugin(const Ref<Resource> & p_for_resource)5454 Vector<Ref<EditorResourceConversionPlugin> > EditorNode::find_resource_conversion_plugin(const Ref<Resource> &p_for_resource) {
5455 
5456 	Vector<Ref<EditorResourceConversionPlugin> > ret;
5457 
5458 	for (int i = 0; i < resource_conversion_plugins.size(); i++) {
5459 		if (resource_conversion_plugins[i].is_valid() && resource_conversion_plugins[i]->handles(p_for_resource)) {
5460 			ret.push_back(resource_conversion_plugins[i]);
5461 		}
5462 	}
5463 
5464 	return ret;
5465 }
5466 
_bottom_panel_raise_toggled(bool p_pressed)5467 void EditorNode::_bottom_panel_raise_toggled(bool p_pressed) {
5468 
5469 	top_split->set_visible(!p_pressed);
5470 }
5471 
_update_video_driver_color()5472 void EditorNode::_update_video_driver_color() {
5473 
5474 	// TODO: Probably should de-hardcode this and add to editor settings.
5475 	if (video_driver->get_text() == "GLES2") {
5476 		video_driver->add_color_override("font_color", Color::hex(0x5586a4ff));
5477 	} else if (video_driver->get_text() == "GLES3") {
5478 		video_driver->add_color_override("font_color", Color::hex(0xa5557dff));
5479 	}
5480 }
5481 
_video_driver_selected(int p_which)5482 void EditorNode::_video_driver_selected(int p_which) {
5483 
5484 	String driver = video_driver->get_item_metadata(p_which);
5485 
5486 	String current = OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver());
5487 
5488 	if (driver == current) {
5489 		return;
5490 	}
5491 
5492 	video_driver_request = driver;
5493 	video_restart_dialog->popup_centered_minsize();
5494 	video_driver->select(video_driver_current);
5495 	_update_video_driver_color();
5496 }
5497 
_resource_saved(RES p_resource,const String & p_path)5498 void EditorNode::_resource_saved(RES p_resource, const String &p_path) {
5499 	if (EditorFileSystem::get_singleton()) {
5500 		EditorFileSystem::get_singleton()->update_file(p_path);
5501 	}
5502 
5503 	singleton->editor_folding.save_resource_folding(p_resource, p_path);
5504 }
5505 
_resource_loaded(RES p_resource,const String & p_path)5506 void EditorNode::_resource_loaded(RES p_resource, const String &p_path) {
5507 
5508 	singleton->editor_folding.load_resource_folding(p_resource, p_path);
5509 }
5510 
_feature_profile_changed()5511 void EditorNode::_feature_profile_changed() {
5512 
5513 	Ref<EditorFeatureProfile> profile = feature_profile_manager->get_current_profile();
5514 	TabContainer *import_tabs = cast_to<TabContainer>(import_dock->get_parent());
5515 	TabContainer *node_tabs = cast_to<TabContainer>(node_dock->get_parent());
5516 	TabContainer *fs_tabs = cast_to<TabContainer>(filesystem_dock->get_parent());
5517 	if (profile.is_valid()) {
5518 
5519 		import_tabs->set_tab_hidden(import_dock->get_index(), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_IMPORT_DOCK));
5520 		node_tabs->set_tab_hidden(node_dock->get_index(), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_NODE_DOCK));
5521 		fs_tabs->set_tab_hidden(filesystem_dock->get_index(), profile->is_feature_disabled(EditorFeatureProfile::FEATURE_FILESYSTEM_DOCK));
5522 
5523 		main_editor_buttons[EDITOR_3D]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D));
5524 		main_editor_buttons[EDITOR_SCRIPT]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT));
5525 		if (StreamPeerSSL::is_available())
5526 			main_editor_buttons[EDITOR_ASSETLIB]->set_visible(!profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB));
5527 		if ((profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D) && singleton->main_editor_buttons[EDITOR_3D]->is_pressed()) ||
5528 				(profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT) && singleton->main_editor_buttons[EDITOR_SCRIPT]->is_pressed()) ||
5529 				(StreamPeerSSL::is_available() && profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB) && singleton->main_editor_buttons[EDITOR_ASSETLIB]->is_pressed())) {
5530 			_editor_select(EDITOR_2D);
5531 		}
5532 	} else {
5533 
5534 		import_tabs->set_tab_hidden(import_dock->get_index(), false);
5535 		node_tabs->set_tab_hidden(node_dock->get_index(), false);
5536 		fs_tabs->set_tab_hidden(filesystem_dock->get_index(), false);
5537 		import_dock->set_visible(true);
5538 		node_dock->set_visible(true);
5539 		filesystem_dock->set_visible(true);
5540 		main_editor_buttons[EDITOR_3D]->set_visible(true);
5541 		main_editor_buttons[EDITOR_SCRIPT]->set_visible(true);
5542 		if (StreamPeerSSL::is_available())
5543 			main_editor_buttons[EDITOR_ASSETLIB]->set_visible(true);
5544 	}
5545 
5546 	_update_dock_slots_visibility();
5547 }
5548 
_bind_methods()5549 void EditorNode::_bind_methods() {
5550 
5551 	ClassDB::bind_method("_menu_option", &EditorNode::_menu_option);
5552 	ClassDB::bind_method("_tool_menu_option", &EditorNode::_tool_menu_option);
5553 	ClassDB::bind_method("_menu_confirm_current", &EditorNode::_menu_confirm_current);
5554 	ClassDB::bind_method("_dialog_action", &EditorNode::_dialog_action);
5555 	ClassDB::bind_method("_editor_select", &EditorNode::_editor_select);
5556 	ClassDB::bind_method("_node_renamed", &EditorNode::_node_renamed);
5557 	ClassDB::bind_method("edit_node", &EditorNode::edit_node);
5558 	ClassDB::bind_method("_unhandled_input", &EditorNode::_unhandled_input);
5559 	ClassDB::bind_method("_update_file_menu_opened", &EditorNode::_update_file_menu_opened);
5560 	ClassDB::bind_method("_update_file_menu_closed", &EditorNode::_update_file_menu_closed);
5561 
5562 	ClassDB::bind_method(D_METHOD("push_item", "object", "property", "inspector_only"), &EditorNode::push_item, DEFVAL(""), DEFVAL(false));
5563 
5564 	ClassDB::bind_method("_get_scene_metadata", &EditorNode::_get_scene_metadata);
5565 	ClassDB::bind_method("set_edited_scene", &EditorNode::set_edited_scene);
5566 	ClassDB::bind_method("open_request", &EditorNode::open_request);
5567 	ClassDB::bind_method("_inherit_request", &EditorNode::_inherit_request);
5568 	ClassDB::bind_method("_instance_request", &EditorNode::_instance_request);
5569 	ClassDB::bind_method("_close_messages", &EditorNode::_close_messages);
5570 	ClassDB::bind_method("_show_messages", &EditorNode::_show_messages);
5571 	ClassDB::bind_method("_vp_resized", &EditorNode::_vp_resized);
5572 	ClassDB::bind_method("_quick_opened", &EditorNode::_quick_opened);
5573 	ClassDB::bind_method("_quick_run", &EditorNode::_quick_run);
5574 
5575 	ClassDB::bind_method("_open_recent_scene", &EditorNode::_open_recent_scene);
5576 
5577 	ClassDB::bind_method("stop_child_process", &EditorNode::stop_child_process);
5578 
5579 	ClassDB::bind_method("get_script_create_dialog", &EditorNode::get_script_create_dialog);
5580 
5581 	ClassDB::bind_method("_sources_changed", &EditorNode::_sources_changed);
5582 	ClassDB::bind_method("_fs_changed", &EditorNode::_fs_changed);
5583 	ClassDB::bind_method("_dock_select_draw", &EditorNode::_dock_select_draw);
5584 	ClassDB::bind_method("_dock_select_input", &EditorNode::_dock_select_input);
5585 	ClassDB::bind_method("_dock_pre_popup", &EditorNode::_dock_pre_popup);
5586 	ClassDB::bind_method("_dock_split_dragged", &EditorNode::_dock_split_dragged);
5587 	ClassDB::bind_method("_save_docks", &EditorNode::_save_docks);
5588 	ClassDB::bind_method("_dock_popup_exit", &EditorNode::_dock_popup_exit);
5589 	ClassDB::bind_method("_dock_move_left", &EditorNode::_dock_move_left);
5590 	ClassDB::bind_method("_dock_move_right", &EditorNode::_dock_move_right);
5591 	ClassDB::bind_method("_dock_tab_changed", &EditorNode::_dock_tab_changed);
5592 
5593 	ClassDB::bind_method("_layout_menu_option", &EditorNode::_layout_menu_option);
5594 
5595 	ClassDB::bind_method("set_current_scene", &EditorNode::set_current_scene);
5596 	ClassDB::bind_method("set_current_version", &EditorNode::set_current_version);
5597 	ClassDB::bind_method("_scene_tab_changed", &EditorNode::_scene_tab_changed);
5598 	ClassDB::bind_method("_scene_tab_closed", &EditorNode::_scene_tab_closed);
5599 	ClassDB::bind_method("_scene_tab_hover", &EditorNode::_scene_tab_hover);
5600 	ClassDB::bind_method("_scene_tab_exit", &EditorNode::_scene_tab_exit);
5601 	ClassDB::bind_method("_scene_tab_input", &EditorNode::_scene_tab_input);
5602 	ClassDB::bind_method("_reposition_active_tab", &EditorNode::_reposition_active_tab);
5603 	ClassDB::bind_method("_thumbnail_done", &EditorNode::_thumbnail_done);
5604 	ClassDB::bind_method("_scene_tab_script_edited", &EditorNode::_scene_tab_script_edited);
5605 	ClassDB::bind_method("_set_main_scene_state", &EditorNode::_set_main_scene_state);
5606 	ClassDB::bind_method("_update_scene_tabs", &EditorNode::_update_scene_tabs);
5607 	ClassDB::bind_method("_discard_changes", &EditorNode::_discard_changes);
5608 	ClassDB::bind_method("_update_recent_scenes", &EditorNode::_update_recent_scenes);
5609 
5610 	ClassDB::bind_method("_clear_undo_history", &EditorNode::_clear_undo_history);
5611 	ClassDB::bind_method("_dropped_files", &EditorNode::_dropped_files);
5612 	ClassDB::bind_method(D_METHOD("_global_menu_action"), &EditorNode::_global_menu_action, DEFVAL(Variant()));
5613 	ClassDB::bind_method("_toggle_distraction_free_mode", &EditorNode::_toggle_distraction_free_mode);
5614 	ClassDB::bind_method("_version_control_menu_option", &EditorNode::_version_control_menu_option);
5615 	ClassDB::bind_method("edit_item_resource", &EditorNode::edit_item_resource);
5616 
5617 	ClassDB::bind_method(D_METHOD("get_gui_base"), &EditorNode::get_gui_base);
5618 	ClassDB::bind_method(D_METHOD("_bottom_panel_switch"), &EditorNode::_bottom_panel_switch);
5619 
5620 	ClassDB::bind_method(D_METHOD("_open_imported"), &EditorNode::_open_imported);
5621 	ClassDB::bind_method(D_METHOD("_inherit_imported"), &EditorNode::_inherit_imported);
5622 
5623 	ClassDB::bind_method("_copy_warning", &EditorNode::_copy_warning);
5624 
5625 	ClassDB::bind_method(D_METHOD("_resources_reimported"), &EditorNode::_resources_reimported);
5626 	ClassDB::bind_method(D_METHOD("_bottom_panel_raise_toggled"), &EditorNode::_bottom_panel_raise_toggled);
5627 
5628 	ClassDB::bind_method(D_METHOD("_on_plugin_ready"), &EditorNode::_on_plugin_ready);
5629 
5630 	ClassDB::bind_method(D_METHOD("_video_driver_selected"), &EditorNode::_video_driver_selected);
5631 
5632 	ClassDB::bind_method(D_METHOD("_resources_changed"), &EditorNode::_resources_changed);
5633 	ClassDB::bind_method(D_METHOD("_feature_profile_changed"), &EditorNode::_feature_profile_changed);
5634 
5635 	ClassDB::bind_method("_screenshot", &EditorNode::_screenshot);
5636 	ClassDB::bind_method("_request_screenshot", &EditorNode::_request_screenshot);
5637 	ClassDB::bind_method("_save_screenshot", &EditorNode::_save_screenshot);
5638 
5639 	ADD_SIGNAL(MethodInfo("play_pressed"));
5640 	ADD_SIGNAL(MethodInfo("pause_pressed"));
5641 	ADD_SIGNAL(MethodInfo("stop_pressed"));
5642 	ADD_SIGNAL(MethodInfo("request_help_search"));
5643 	ADD_SIGNAL(MethodInfo("script_add_function_request", PropertyInfo(Variant::OBJECT, "obj"), PropertyInfo(Variant::STRING, "function"), PropertyInfo(Variant::POOL_STRING_ARRAY, "args")));
5644 	ADD_SIGNAL(MethodInfo("resource_saved", PropertyInfo(Variant::OBJECT, "obj")));
5645 }
5646 
_resource_get_edited_scene()5647 static Node *_resource_get_edited_scene() {
5648 
5649 	return EditorNode::get_singleton()->get_edited_scene();
5650 }
5651 
_print_handler(void * p_this,const String & p_string,bool p_error)5652 void EditorNode::_print_handler(void *p_this, const String &p_string, bool p_error) {
5653 	EditorNode *en = (EditorNode *)p_this;
5654 	en->log->add_message(p_string, p_error ? EditorLog::MSG_TYPE_ERROR : EditorLog::MSG_TYPE_STD);
5655 }
5656 
_execute_thread(void * p_ud)5657 static void _execute_thread(void *p_ud) {
5658 
5659 	EditorNode::ExecuteThreadArgs *eta = (EditorNode::ExecuteThreadArgs *)p_ud;
5660 	Error err = OS::get_singleton()->execute(eta->path, eta->args, true, NULL, &eta->output, &eta->exitcode, true, eta->execute_output_mutex);
5661 	print_verbose("Thread exit status: " + itos(eta->exitcode));
5662 	if (err != OK) {
5663 		eta->exitcode = err;
5664 	}
5665 
5666 	eta->done = true;
5667 }
5668 
execute_and_show_output(const String & p_title,const String & p_path,const List<String> & p_arguments,bool p_close_on_ok,bool p_close_on_errors)5669 int EditorNode::execute_and_show_output(const String &p_title, const String &p_path, const List<String> &p_arguments, bool p_close_on_ok, bool p_close_on_errors) {
5670 
5671 	execute_output_dialog->set_title(p_title);
5672 	execute_output_dialog->get_ok()->set_disabled(true);
5673 	execute_outputs->clear();
5674 	execute_outputs->set_scroll_follow(true);
5675 	execute_output_dialog->popup_centered_ratio();
5676 
5677 	ExecuteThreadArgs eta;
5678 	eta.path = p_path;
5679 	eta.args = p_arguments;
5680 	eta.execute_output_mutex = Mutex::create();
5681 	eta.exitcode = 255;
5682 	eta.done = false;
5683 
5684 	int prev_len = 0;
5685 
5686 	eta.execute_output_thread = Thread::create(_execute_thread, &eta);
5687 
5688 	ERR_FAIL_COND_V(!eta.execute_output_thread, 0);
5689 
5690 	while (!eta.done) {
5691 		eta.execute_output_mutex->lock();
5692 		if (prev_len != eta.output.length()) {
5693 			String to_add = eta.output.substr(prev_len, eta.output.length());
5694 			prev_len = eta.output.length();
5695 			execute_outputs->add_text(to_add);
5696 			Main::iteration();
5697 		}
5698 		eta.execute_output_mutex->unlock();
5699 		OS::get_singleton()->delay_usec(1000);
5700 	}
5701 
5702 	Thread::wait_to_finish(eta.execute_output_thread);
5703 	memdelete(eta.execute_output_thread);
5704 	memdelete(eta.execute_output_mutex);
5705 	execute_outputs->add_text("\nExit Code: " + itos(eta.exitcode));
5706 
5707 	if (p_close_on_errors && eta.exitcode != 0) {
5708 		execute_output_dialog->hide();
5709 	}
5710 	if (p_close_on_ok && eta.exitcode == 0) {
5711 		execute_output_dialog->hide();
5712 	}
5713 
5714 	execute_output_dialog->get_ok()->set_disabled(false);
5715 
5716 	return eta.exitcode;
5717 }
5718 
EditorNode()5719 EditorNode::EditorNode() {
5720 
5721 	Input::get_singleton()->set_use_accumulated_input(true);
5722 	Resource::_get_local_scene_func = _resource_get_edited_scene;
5723 
5724 	VisualServer::get_singleton()->textures_keep_original(true);
5725 	VisualServer::get_singleton()->set_debug_generate_wireframes(true);
5726 
5727 	PhysicsServer::get_singleton()->set_active(false); // no physics by default if editor
5728 	Physics2DServer::get_singleton()->set_active(false); // no physics by default if editor
5729 	ScriptServer::set_scripting_enabled(false); // no scripting by default if editor
5730 
5731 	EditorHelp::generate_doc(); //before any editor classes are created
5732 	SceneState::set_disable_placeholders(true);
5733 	ResourceLoader::clear_translation_remaps(); //no remaps using during editor
5734 	ResourceLoader::clear_path_remaps();
5735 
5736 	InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
5737 
5738 	if (id) {
5739 
5740 		if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) {
5741 			//only if no touchscreen ui hint, set emulation
5742 			id->set_emulate_touch_from_mouse(false); //just disable just in case
5743 		}
5744 		id->set_custom_mouse_cursor(RES());
5745 	}
5746 
5747 	singleton = this;
5748 	exiting = false;
5749 	dimmed = false;
5750 	last_checked_version = 0;
5751 	changing_scene = false;
5752 	_initializing_addons = false;
5753 	docks_visible = true;
5754 	restoring_scenes = false;
5755 	cmdline_export_mode = false;
5756 	scene_distraction = false;
5757 	script_distraction = false;
5758 
5759 	TranslationServer::get_singleton()->set_enabled(false);
5760 	// load settings
5761 	if (!EditorSettings::get_singleton())
5762 		EditorSettings::create();
5763 
5764 	FileAccess::set_backup_save(EDITOR_GET("filesystem/on_save/safe_save_on_backup_then_rename"));
5765 
5766 	{
5767 		int display_scale = EditorSettings::get_singleton()->get("interface/editor/display_scale");
5768 		float custom_display_scale = EditorSettings::get_singleton()->get("interface/editor/custom_display_scale");
5769 
5770 		switch (display_scale) {
5771 			case 0: {
5772 				// Try applying a suitable display scale automatically
5773 #ifdef OSX_ENABLED
5774 				editor_set_scale(OS::get_singleton()->get_screen_max_scale());
5775 #else
5776 				const int screen = OS::get_singleton()->get_current_screen();
5777 				editor_set_scale(OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).x > 2000 ? 2.0 : 1.0);
5778 #endif
5779 			} break;
5780 
5781 			case 1: {
5782 				editor_set_scale(0.75);
5783 			} break;
5784 
5785 			case 2: {
5786 				editor_set_scale(1.0);
5787 			} break;
5788 
5789 			case 3: {
5790 				editor_set_scale(1.25);
5791 			} break;
5792 
5793 			case 4: {
5794 				editor_set_scale(1.5);
5795 			} break;
5796 
5797 			case 5: {
5798 				editor_set_scale(1.75);
5799 			} break;
5800 
5801 			case 6: {
5802 				editor_set_scale(2.0);
5803 			} break;
5804 
5805 			default: {
5806 				editor_set_scale(custom_display_scale);
5807 			} break;
5808 		}
5809 	}
5810 
5811 	// Define a minimum window size to prevent UI elements from overlapping or being cut off
5812 	OS::get_singleton()->set_min_window_size(Size2(1024, 600) * EDSCALE);
5813 
5814 	ResourceLoader::set_abort_on_missing_resources(false);
5815 	FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files"));
5816 	EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files"));
5817 	EditorFileDialog::set_default_display_mode((EditorFileDialog::DisplayMode)EditorSettings::get_singleton()->get("filesystem/file_dialog/display_mode").operator int());
5818 	ResourceLoader::set_error_notify_func(this, _load_error_notify);
5819 	ResourceLoader::set_dependency_error_notify_func(this, _dependency_error_report);
5820 
5821 	{ //register importers at the beginning, so dialogs are created with the right extensions
5822 		Ref<ResourceImporterTexture> import_texture;
5823 		import_texture.instance();
5824 		ResourceFormatImporter::get_singleton()->add_importer(import_texture);
5825 
5826 		Ref<ResourceImporterLayeredTexture> import_3d;
5827 		import_3d.instance();
5828 		import_3d->set_3d(true);
5829 		ResourceFormatImporter::get_singleton()->add_importer(import_3d);
5830 
5831 		Ref<ResourceImporterLayeredTexture> import_array;
5832 		import_array.instance();
5833 		import_array->set_3d(false);
5834 		ResourceFormatImporter::get_singleton()->add_importer(import_array);
5835 
5836 		Ref<ResourceImporterImage> import_image;
5837 		import_image.instance();
5838 		ResourceFormatImporter::get_singleton()->add_importer(import_image);
5839 
5840 		Ref<ResourceImporterTextureAtlas> import_texture_atlas;
5841 		import_texture_atlas.instance();
5842 		ResourceFormatImporter::get_singleton()->add_importer(import_texture_atlas);
5843 
5844 		Ref<ResourceImporterCSVTranslation> import_csv_translation;
5845 		import_csv_translation.instance();
5846 		ResourceFormatImporter::get_singleton()->add_importer(import_csv_translation);
5847 
5848 		Ref<ResourceImporterCSV> import_csv;
5849 		import_csv.instance();
5850 		ResourceFormatImporter::get_singleton()->add_importer(import_csv);
5851 
5852 		Ref<ResourceImporterWAV> import_wav;
5853 		import_wav.instance();
5854 		ResourceFormatImporter::get_singleton()->add_importer(import_wav);
5855 
5856 		Ref<ResourceImporterOBJ> import_obj;
5857 		import_obj.instance();
5858 		ResourceFormatImporter::get_singleton()->add_importer(import_obj);
5859 
5860 		Ref<ResourceImporterScene> import_scene;
5861 		import_scene.instance();
5862 		ResourceFormatImporter::get_singleton()->add_importer(import_scene);
5863 
5864 		{
5865 			Ref<EditorSceneImporterCollada> import_collada;
5866 			import_collada.instance();
5867 			import_scene->add_importer(import_collada);
5868 
5869 			Ref<EditorOBJImporter> import_obj2;
5870 			import_obj2.instance();
5871 			import_scene->add_importer(import_obj2);
5872 
5873 			Ref<EditorSceneImporterGLTF> import_gltf;
5874 			import_gltf.instance();
5875 			import_scene->add_importer(import_gltf);
5876 
5877 			Ref<EditorSceneImporterESCN> import_escn;
5878 			import_escn.instance();
5879 			import_scene->add_importer(import_escn);
5880 		}
5881 
5882 		Ref<ResourceImporterBitMap> import_bitmap;
5883 		import_bitmap.instance();
5884 		ResourceFormatImporter::get_singleton()->add_importer(import_bitmap);
5885 	}
5886 
5887 	{
5888 		Ref<EditorInspectorDefaultPlugin> eidp;
5889 		eidp.instance();
5890 		EditorInspector::add_inspector_plugin(eidp);
5891 
5892 		Ref<EditorInspectorRootMotionPlugin> rmp;
5893 		rmp.instance();
5894 		EditorInspector::add_inspector_plugin(rmp);
5895 
5896 		Ref<EditorInspectorShaderModePlugin> smp;
5897 		smp.instance();
5898 		EditorInspector::add_inspector_plugin(smp);
5899 	}
5900 
5901 	_pvrtc_register_compressors();
5902 
5903 	editor_selection = memnew(EditorSelection);
5904 
5905 	EditorFileSystem *efs = memnew(EditorFileSystem);
5906 	add_child(efs);
5907 
5908 	//used for previews
5909 	FileDialog::get_icon_func = _file_dialog_get_icon;
5910 	FileDialog::register_func = _file_dialog_register;
5911 	FileDialog::unregister_func = _file_dialog_unregister;
5912 
5913 	EditorFileDialog::get_icon_func = _file_dialog_get_icon;
5914 	EditorFileDialog::register_func = _editor_file_dialog_register;
5915 	EditorFileDialog::unregister_func = _editor_file_dialog_unregister;
5916 
5917 	editor_export = memnew(EditorExport);
5918 	add_child(editor_export);
5919 
5920 	// Exporters might need the theme
5921 	theme = create_custom_theme();
5922 
5923 	register_exporters();
5924 
5925 	GLOBAL_DEF("editor/main_run_args", "");
5926 
5927 	ClassDB::set_class_enabled("RootMotionView", true);
5928 
5929 	//defs here, use EDITOR_GET in logic
5930 	EDITOR_DEF_RST("interface/scene_tabs/always_show_close_button", false);
5931 	EDITOR_DEF_RST("interface/scene_tabs/resize_if_many_tabs", true);
5932 	EDITOR_DEF_RST("interface/scene_tabs/minimum_width", 50);
5933 	EDITOR_DEF("run/output/always_clear_output_on_play", true);
5934 	EDITOR_DEF("run/output/always_open_output_on_play", true);
5935 	EDITOR_DEF("run/output/always_close_output_on_stop", true);
5936 	EDITOR_DEF("run/auto_save/save_before_running", true);
5937 	EDITOR_DEF_RST("interface/editor/save_each_scene_on_quit", true);
5938 	EDITOR_DEF("interface/editor/quit_confirmation", true);
5939 	EDITOR_DEF("interface/editor/show_update_spinner", false);
5940 	EDITOR_DEF("interface/editor/update_continuously", false);
5941 	EDITOR_DEF_RST("interface/scene_tabs/restore_scenes_on_load", false);
5942 	EDITOR_DEF_RST("interface/scene_tabs/show_thumbnail_on_hover", true);
5943 	EDITOR_DEF_RST("interface/inspector/capitalize_properties", true);
5944 	EDITOR_DEF_RST("interface/inspector/default_float_step", 0.001);
5945 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::REAL, "interface/inspector/default_float_step", PROPERTY_HINT_RANGE, "0,1,0"));
5946 	EDITOR_DEF_RST("interface/inspector/disable_folding", false);
5947 	EDITOR_DEF_RST("interface/inspector/auto_unfold_foreign_scenes", true);
5948 	EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false);
5949 	EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true);
5950 	EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true);
5951 	EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "SpatialMaterial,Script,MeshLibrary,TileSet");
5952 	EDITOR_DEF("interface/inspector/default_color_picker_mode", 0);
5953 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW", PROPERTY_USAGE_DEFAULT));
5954 	EDITOR_DEF("run/auto_save/save_before_running", true);
5955 
5956 	theme_base = memnew(Control);
5957 	add_child(theme_base);
5958 	theme_base->set_anchors_and_margins_preset(Control::PRESET_WIDE);
5959 
5960 	gui_base = memnew(Panel);
5961 	theme_base->add_child(gui_base);
5962 	gui_base->set_anchors_and_margins_preset(Control::PRESET_WIDE);
5963 
5964 	theme_base->set_theme(theme);
5965 	gui_base->set_theme(theme);
5966 	gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles"));
5967 
5968 	resource_preview = memnew(EditorResourcePreview);
5969 	add_child(resource_preview);
5970 	progress_dialog = memnew(ProgressDialog);
5971 	gui_base->add_child(progress_dialog);
5972 
5973 	// take up all screen
5974 	gui_base->set_anchor(MARGIN_RIGHT, Control::ANCHOR_END);
5975 	gui_base->set_anchor(MARGIN_BOTTOM, Control::ANCHOR_END);
5976 	gui_base->set_end(Point2(0, 0));
5977 
5978 	main_vbox = memnew(VBoxContainer);
5979 	gui_base->add_child(main_vbox);
5980 	main_vbox->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8);
5981 	main_vbox->add_constant_override("separation", 8 * EDSCALE);
5982 
5983 	menu_hb = memnew(HBoxContainer);
5984 	main_vbox->add_child(menu_hb);
5985 
5986 	left_l_hsplit = memnew(HSplitContainer);
5987 	main_vbox->add_child(left_l_hsplit);
5988 
5989 	left_l_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
5990 
5991 	left_l_vsplit = memnew(VSplitContainer);
5992 	left_l_hsplit->add_child(left_l_vsplit);
5993 	dock_slot[DOCK_SLOT_LEFT_UL] = memnew(TabContainer);
5994 	left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UL]);
5995 	dock_slot[DOCK_SLOT_LEFT_BL] = memnew(TabContainer);
5996 	left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BL]);
5997 
5998 	left_r_hsplit = memnew(HSplitContainer);
5999 	left_l_hsplit->add_child(left_r_hsplit);
6000 	left_r_vsplit = memnew(VSplitContainer);
6001 	left_r_hsplit->add_child(left_r_vsplit);
6002 	dock_slot[DOCK_SLOT_LEFT_UR] = memnew(TabContainer);
6003 	left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UR]);
6004 	dock_slot[DOCK_SLOT_LEFT_BR] = memnew(TabContainer);
6005 	left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BR]);
6006 
6007 	main_hsplit = memnew(HSplitContainer);
6008 	left_r_hsplit->add_child(main_hsplit);
6009 	VBoxContainer *center_vb = memnew(VBoxContainer);
6010 	main_hsplit->add_child(center_vb);
6011 	center_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
6012 
6013 	center_split = memnew(VSplitContainer);
6014 	center_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
6015 	center_split->set_collapsed(false);
6016 	center_vb->add_child(center_split);
6017 
6018 	right_hsplit = memnew(HSplitContainer);
6019 	main_hsplit->add_child(right_hsplit);
6020 
6021 	right_l_vsplit = memnew(VSplitContainer);
6022 	right_hsplit->add_child(right_l_vsplit);
6023 	dock_slot[DOCK_SLOT_RIGHT_UL] = memnew(TabContainer);
6024 	right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UL]);
6025 	dock_slot[DOCK_SLOT_RIGHT_BL] = memnew(TabContainer);
6026 	right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BL]);
6027 
6028 	right_r_vsplit = memnew(VSplitContainer);
6029 	right_hsplit->add_child(right_r_vsplit);
6030 	dock_slot[DOCK_SLOT_RIGHT_UR] = memnew(TabContainer);
6031 	right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UR]);
6032 	dock_slot[DOCK_SLOT_RIGHT_BR] = memnew(TabContainer);
6033 	right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BR]);
6034 
6035 	// Store them for easier access
6036 	vsplits.push_back(left_l_vsplit);
6037 	vsplits.push_back(left_r_vsplit);
6038 	vsplits.push_back(right_l_vsplit);
6039 	vsplits.push_back(right_r_vsplit);
6040 
6041 	hsplits.push_back(left_l_hsplit);
6042 	hsplits.push_back(left_r_hsplit);
6043 	hsplits.push_back(main_hsplit);
6044 	hsplits.push_back(right_hsplit);
6045 
6046 	for (int i = 0; i < vsplits.size(); i++) {
6047 		vsplits[i]->connect("dragged", this, "_dock_split_dragged");
6048 		hsplits[i]->connect("dragged", this, "_dock_split_dragged");
6049 	}
6050 
6051 	dock_select_popup = memnew(PopupPanel);
6052 	gui_base->add_child(dock_select_popup);
6053 	VBoxContainer *dock_vb = memnew(VBoxContainer);
6054 	dock_select_popup->add_child(dock_vb);
6055 
6056 	HBoxContainer *dock_hb = memnew(HBoxContainer);
6057 	dock_tab_move_left = memnew(ToolButton);
6058 	dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons"));
6059 	dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE);
6060 	dock_tab_move_left->connect("pressed", this, "_dock_move_left");
6061 	dock_hb->add_child(dock_tab_move_left);
6062 
6063 	Label *dock_label = memnew(Label);
6064 	dock_label->set_text(TTR("Dock Position"));
6065 	dock_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
6066 	dock_label->set_align(Label::ALIGN_CENTER);
6067 	dock_hb->add_child(dock_label);
6068 
6069 	dock_tab_move_right = memnew(ToolButton);
6070 	dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons"));
6071 	dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE);
6072 	dock_tab_move_right->connect("pressed", this, "_dock_move_right");
6073 
6074 	dock_hb->add_child(dock_tab_move_right);
6075 	dock_vb->add_child(dock_hb);
6076 
6077 	dock_select = memnew(Control);
6078 	dock_select->set_custom_minimum_size(Size2(128, 64) * EDSCALE);
6079 	dock_select->connect("gui_input", this, "_dock_select_input");
6080 	dock_select->connect("draw", this, "_dock_select_draw");
6081 	dock_select->connect("mouse_exited", this, "_dock_popup_exit");
6082 	dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL);
6083 	dock_vb->add_child(dock_select);
6084 
6085 	dock_select_popup->set_as_minsize();
6086 	dock_select_rect_over = -1;
6087 	dock_popup_selected = -1;
6088 	for (int i = 0; i < DOCK_SLOT_MAX; i++) {
6089 		dock_slot[i]->set_custom_minimum_size(Size2(170, 0) * EDSCALE);
6090 		dock_slot[i]->set_v_size_flags(Control::SIZE_EXPAND_FILL);
6091 		dock_slot[i]->set_popup(dock_select_popup);
6092 		dock_slot[i]->connect("pre_popup_pressed", this, "_dock_pre_popup", varray(i));
6093 		dock_slot[i]->set_tab_align(TabContainer::ALIGN_LEFT);
6094 		dock_slot[i]->set_drag_to_rearrange_enabled(true);
6095 		dock_slot[i]->set_tabs_rearrange_group(1);
6096 		dock_slot[i]->connect("tab_changed", this, "_dock_tab_changed");
6097 		dock_slot[i]->set_use_hidden_tabs_for_min_size(true);
6098 	}
6099 
6100 	dock_drag_timer = memnew(Timer);
6101 	add_child(dock_drag_timer);
6102 	dock_drag_timer->set_wait_time(0.5);
6103 	dock_drag_timer->set_one_shot(true);
6104 	dock_drag_timer->connect("timeout", this, "_save_docks");
6105 
6106 	top_split = memnew(VSplitContainer);
6107 	center_split->add_child(top_split);
6108 	top_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
6109 	top_split->set_collapsed(true);
6110 
6111 	VBoxContainer *srt = memnew(VBoxContainer);
6112 	srt->set_v_size_flags(Control::SIZE_EXPAND_FILL);
6113 	top_split->add_child(srt);
6114 	srt->add_constant_override("separation", 0);
6115 
6116 	tab_preview_panel = memnew(Panel);
6117 	tab_preview_panel->set_size(Size2(100, 100) * EDSCALE);
6118 	tab_preview_panel->hide();
6119 	tab_preview_panel->set_self_modulate(Color(1, 1, 1, 0.7));
6120 	gui_base->add_child(tab_preview_panel);
6121 
6122 	tab_preview = memnew(TextureRect);
6123 	tab_preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
6124 	tab_preview->set_size(Size2(96, 96) * EDSCALE);
6125 	tab_preview->set_position(Point2(2, 2) * EDSCALE);
6126 	tab_preview_panel->add_child(tab_preview);
6127 
6128 	scene_tabs = memnew(Tabs);
6129 	scene_tabs->add_style_override("tab_fg", gui_base->get_stylebox("SceneTabFG", "EditorStyles"));
6130 	scene_tabs->add_style_override("tab_bg", gui_base->get_stylebox("SceneTabBG", "EditorStyles"));
6131 	scene_tabs->set_select_with_rmb(true);
6132 	scene_tabs->add_tab("unsaved");
6133 	scene_tabs->set_tab_align(Tabs::ALIGN_LEFT);
6134 	scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
6135 	scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE);
6136 	scene_tabs->set_drag_to_rearrange_enabled(true);
6137 	scene_tabs->connect("tab_changed", this, "_scene_tab_changed");
6138 	scene_tabs->connect("right_button_pressed", this, "_scene_tab_script_edited");
6139 	scene_tabs->connect("tab_close", this, "_scene_tab_closed", varray(SCENE_TAB_CLOSE));
6140 	scene_tabs->connect("tab_hover", this, "_scene_tab_hover");
6141 	scene_tabs->connect("mouse_exited", this, "_scene_tab_exit");
6142 	scene_tabs->connect("gui_input", this, "_scene_tab_input");
6143 	scene_tabs->connect("reposition_active_tab_request", this, "_reposition_active_tab");
6144 	scene_tabs->connect("resized", this, "_update_scene_tabs");
6145 
6146 	tabbar_container = memnew(HBoxContainer);
6147 	scene_tabs->set_h_size_flags(Control::SIZE_EXPAND_FILL);
6148 
6149 	scene_tabs_context_menu = memnew(PopupMenu);
6150 	tabbar_container->add_child(scene_tabs_context_menu);
6151 	scene_tabs_context_menu->connect("id_pressed", this, "_menu_option");
6152 	scene_tabs_context_menu->set_hide_on_window_lose_focus(true);
6153 
6154 	srt->add_child(tabbar_container);
6155 	tabbar_container->add_child(scene_tabs);
6156 	distraction_free = memnew(ToolButton);
6157 #ifdef OSX_ENABLED
6158 	distraction_free->set_shortcut(ED_SHORTCUT("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_D));
6159 #else
6160 	distraction_free->set_shortcut(ED_SHORTCUT("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F11));
6161 #endif
6162 	distraction_free->set_tooltip(TTR("Toggle distraction-free mode."));
6163 	distraction_free->connect("pressed", this, "_toggle_distraction_free_mode");
6164 	distraction_free->set_icon(gui_base->get_icon("DistractionFree", "EditorIcons"));
6165 	distraction_free->set_toggle_mode(true);
6166 
6167 	scene_tab_add = memnew(ToolButton);
6168 	tabbar_container->add_child(scene_tab_add);
6169 	tabbar_container->add_child(distraction_free);
6170 	scene_tab_add->set_tooltip(TTR("Add a new scene."));
6171 	scene_tab_add->set_icon(gui_base->get_icon("Add", "EditorIcons"));
6172 	scene_tab_add->add_color_override("icon_color_normal", Color(0.6f, 0.6f, 0.6f, 0.8f));
6173 	scene_tab_add->connect("pressed", this, "_menu_option", make_binds(FILE_NEW_SCENE));
6174 
6175 	scene_root_parent = memnew(PanelContainer);
6176 	scene_root_parent->set_custom_minimum_size(Size2(0, 80) * EDSCALE);
6177 	scene_root_parent->add_style_override("panel", gui_base->get_stylebox("Content", "EditorStyles"));
6178 	scene_root_parent->set_draw_behind_parent(true);
6179 	srt->add_child(scene_root_parent);
6180 	scene_root_parent->set_v_size_flags(Control::SIZE_EXPAND_FILL);
6181 
6182 	scene_root = memnew(Viewport);
6183 	//scene_root->set_usage(Viewport::USAGE_2D); canvas BG mode prevents usage of this as 2D
6184 	scene_root->set_disable_3d(true);
6185 
6186 	VisualServer::get_singleton()->viewport_set_hide_scenario(scene_root->get_viewport_rid(), true);
6187 	scene_root->set_disable_input(true);
6188 	scene_root->set_as_audio_listener_2d(true);
6189 
6190 	viewport = memnew(VBoxContainer);
6191 	viewport->set_v_size_flags(Control::SIZE_EXPAND_FILL);
6192 	viewport->add_constant_override("separation", 0);
6193 	scene_root_parent->add_child(viewport);
6194 
6195 	HBoxContainer *left_menu_hb = memnew(HBoxContainer);
6196 	menu_hb->add_child(left_menu_hb);
6197 
6198 	file_menu = memnew(MenuButton);
6199 	file_menu->set_flat(false);
6200 	file_menu->set_switch_on_hover(true);
6201 	file_menu->set_text(TTR("Scene"));
6202 	file_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
6203 	left_menu_hb->add_child(file_menu);
6204 
6205 	prev_scene = memnew(ToolButton);
6206 	prev_scene->set_icon(gui_base->get_icon("PrevScene", "EditorIcons"));
6207 	prev_scene->set_tooltip(TTR("Go to previously opened scene."));
6208 	prev_scene->set_disabled(true);
6209 	prev_scene->connect("pressed", this, "_menu_option", make_binds(FILE_OPEN_PREV));
6210 	gui_base->add_child(prev_scene);
6211 	prev_scene->set_position(Point2(3, 24));
6212 	prev_scene->hide();
6213 
6214 	accept = memnew(AcceptDialog);
6215 	gui_base->add_child(accept);
6216 	accept->connect("confirmed", this, "_menu_confirm_current");
6217 
6218 	project_export = memnew(ProjectExportDialog);
6219 	gui_base->add_child(project_export);
6220 
6221 	dependency_error = memnew(DependencyErrorDialog);
6222 	gui_base->add_child(dependency_error);
6223 
6224 	dependency_fixer = memnew(DependencyEditor);
6225 	gui_base->add_child(dependency_fixer);
6226 
6227 	settings_config_dialog = memnew(EditorSettingsDialog);
6228 	gui_base->add_child(settings_config_dialog);
6229 
6230 	project_settings = memnew(ProjectSettingsEditor(&editor_data));
6231 	gui_base->add_child(project_settings);
6232 
6233 	run_settings_dialog = memnew(RunSettingsDialog);
6234 	gui_base->add_child(run_settings_dialog);
6235 
6236 	export_template_manager = memnew(ExportTemplateManager);
6237 	gui_base->add_child(export_template_manager);
6238 
6239 	feature_profile_manager = memnew(EditorFeatureProfileManager);
6240 	gui_base->add_child(feature_profile_manager);
6241 	about = memnew(EditorAbout);
6242 	gui_base->add_child(about);
6243 	feature_profile_manager->connect("current_feature_profile_changed", this, "_feature_profile_changed");
6244 
6245 	warning = memnew(AcceptDialog);
6246 	warning->add_button(TTR("Copy Text"), true, "copy");
6247 	gui_base->add_child(warning);
6248 	warning->connect("custom_action", this, "_copy_warning");
6249 
6250 	ED_SHORTCUT("editor/next_tab", TTR("Next tab"), KEY_MASK_CMD + KEY_TAB);
6251 	ED_SHORTCUT("editor/prev_tab", TTR("Previous tab"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_TAB);
6252 	ED_SHORTCUT("editor/filter_files", TTR("Filter Files..."), KEY_MASK_ALT + KEY_MASK_CMD + KEY_P);
6253 	PopupMenu *p;
6254 
6255 	file_menu->set_tooltip(TTR("Operations with scene files."));
6256 
6257 	p = file_menu->get_popup();
6258 	p->set_hide_on_window_lose_focus(true);
6259 	p->add_shortcut(ED_SHORTCUT("editor/new_scene", TTR("New Scene")), FILE_NEW_SCENE);
6260 	p->add_shortcut(ED_SHORTCUT("editor/new_inherited_scene", TTR("New Inherited Scene...")), FILE_NEW_INHERITED_SCENE);
6261 	p->add_shortcut(ED_SHORTCUT("editor/open_scene", TTR("Open Scene..."), KEY_MASK_CMD + KEY_O), FILE_OPEN_SCENE);
6262 	p->add_shortcut(ED_SHORTCUT("editor/reopen_closed_scene", TTR("Reopen Closed Scene"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_T), FILE_OPEN_PREV);
6263 	p->add_submenu_item(TTR("Open Recent"), "RecentScenes", FILE_OPEN_RECENT);
6264 
6265 	p->add_separator();
6266 	p->add_shortcut(ED_SHORTCUT("editor/save_scene", TTR("Save Scene"), KEY_MASK_CMD + KEY_S), FILE_SAVE_SCENE);
6267 	p->add_shortcut(ED_SHORTCUT("editor/save_scene_as", TTR("Save Scene As..."), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_AS_SCENE);
6268 	p->add_shortcut(ED_SHORTCUT("editor/save_all_scenes", TTR("Save All Scenes"), KEY_MASK_ALT + KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_ALL_SCENES);
6269 
6270 	p->add_separator();
6271 	p->add_shortcut(ED_SHORTCUT("editor/quick_open", TTR("Quick Open..."), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_O), FILE_QUICK_OPEN);
6272 	p->add_shortcut(ED_SHORTCUT("editor/quick_open_scene", TTR("Quick Open Scene..."), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_O), FILE_QUICK_OPEN_SCENE);
6273 	p->add_shortcut(ED_SHORTCUT("editor/quick_open_script", TTR("Quick Open Script..."), KEY_MASK_ALT + KEY_MASK_CMD + KEY_O), FILE_QUICK_OPEN_SCRIPT);
6274 
6275 	p->add_separator();
6276 	PopupMenu *pm_export = memnew(PopupMenu);
6277 	pm_export->set_name("Export");
6278 	p->add_child(pm_export);
6279 	p->add_submenu_item(TTR("Convert To..."), "Export");
6280 	pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_MeshLibrary", TTR("MeshLibrary...")), FILE_EXPORT_MESH_LIBRARY);
6281 	pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_TileSet", TTR("TileSet...")), FILE_EXPORT_TILESET);
6282 	pm_export->connect("id_pressed", this, "_menu_option");
6283 
6284 	p->add_separator();
6285 	p->add_shortcut(ED_SHORTCUT("editor/undo", TTR("Undo"), KEY_MASK_CMD + KEY_Z), EDIT_UNDO, true);
6286 	p->add_shortcut(ED_SHORTCUT("editor/redo", TTR("Redo"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_Z), EDIT_REDO, true);
6287 
6288 	p->add_separator();
6289 	p->add_shortcut(ED_SHORTCUT("editor/reload_saved_scene", TTR("Reload Saved Scene")), EDIT_RELOAD_SAVED_SCENE);
6290 	p->add_shortcut(ED_SHORTCUT("editor/close_scene", TTR("Close Scene"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_W), FILE_CLOSE);
6291 
6292 	recent_scenes = memnew(PopupMenu);
6293 	recent_scenes->set_name("RecentScenes");
6294 	p->add_child(recent_scenes);
6295 	recent_scenes->connect("id_pressed", this, "_open_recent_scene");
6296 
6297 	p->add_separator();
6298 	p->add_shortcut(ED_SHORTCUT("editor/file_quit", TTR("Quit"), KEY_MASK_CMD + KEY_Q), FILE_QUIT, true);
6299 
6300 	project_menu = memnew(MenuButton);
6301 	project_menu->set_flat(false);
6302 	project_menu->set_switch_on_hover(true);
6303 	project_menu->set_tooltip(TTR("Miscellaneous project or scene-wide tools."));
6304 	project_menu->set_text(TTR("Project"));
6305 	project_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
6306 	left_menu_hb->add_child(project_menu);
6307 
6308 	p = project_menu->get_popup();
6309 	p->set_hide_on_window_lose_focus(true);
6310 	p->add_shortcut(ED_SHORTCUT("editor/project_settings", TTR("Project Settings...")), RUN_SETTINGS);
6311 	p->connect("id_pressed", this, "_menu_option");
6312 
6313 	vcs_actions_menu = VersionControlEditorPlugin::get_singleton()->get_version_control_actions_panel();
6314 	vcs_actions_menu->set_name("Version Control");
6315 	vcs_actions_menu->connect("index_pressed", this, "_version_control_menu_option");
6316 	p->add_separator();
6317 	p->add_child(vcs_actions_menu);
6318 	p->add_submenu_item(TTR("Version Control"), "Version Control");
6319 	vcs_actions_menu->add_item(TTR("Set Up Version Control"), RUN_VCS_SETTINGS);
6320 	vcs_actions_menu->add_item(TTR("Shut Down Version Control"), RUN_VCS_SHUT_DOWN);
6321 
6322 	p->add_separator();
6323 	p->add_shortcut(ED_SHORTCUT("editor/export", TTR("Export...")), FILE_EXPORT_PROJECT);
6324 	p->add_item(TTR("Install Android Build Template..."), FILE_INSTALL_ANDROID_SOURCE);
6325 	p->add_item(TTR("Open Project Data Folder"), RUN_PROJECT_DATA_FOLDER);
6326 
6327 	plugin_config_dialog = memnew(PluginConfigDialog);
6328 	plugin_config_dialog->connect("plugin_ready", this, "_on_plugin_ready");
6329 	gui_base->add_child(plugin_config_dialog);
6330 
6331 	tool_menu = memnew(PopupMenu);
6332 	tool_menu->set_name("Tools");
6333 	tool_menu->connect("index_pressed", this, "_tool_menu_option");
6334 	p->add_child(tool_menu);
6335 	p->add_submenu_item(TTR("Tools"), "Tools");
6336 	tool_menu->add_item(TTR("Orphan Resource Explorer..."), TOOLS_ORPHAN_RESOURCES);
6337 
6338 	p->add_separator();
6339 #ifdef OSX_ENABLED
6340 	p->add_shortcut(ED_SHORTCUT("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q), RUN_PROJECT_MANAGER, true);
6341 #else
6342 	p->add_shortcut(ED_SHORTCUT("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_Q), RUN_PROJECT_MANAGER, true);
6343 #endif
6344 
6345 	menu_hb->add_spacer();
6346 
6347 	main_editor_button_vb = memnew(HBoxContainer);
6348 	menu_hb->add_child(main_editor_button_vb);
6349 
6350 	debug_menu = memnew(MenuButton);
6351 	debug_menu->set_flat(false);
6352 	debug_menu->set_switch_on_hover(true);
6353 	debug_menu->set_text(TTR("Debug"));
6354 	debug_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
6355 	left_menu_hb->add_child(debug_menu);
6356 
6357 	p = debug_menu->get_popup();
6358 	p->set_hide_on_window_lose_focus(true);
6359 	p->set_hide_on_checkable_item_selection(false);
6360 	p->add_check_shortcut(ED_SHORTCUT("editor/deploy_with_remote_debug", TTR("Deploy with Remote Debug")), RUN_DEPLOY_REMOTE_DEBUG);
6361 	p->set_item_tooltip(p->get_item_count() - 1, TTR("When exporting or deploying, the resulting executable will attempt to connect to the IP of this computer in order to be debugged."));
6362 	p->add_check_shortcut(ED_SHORTCUT("editor/small_deploy_with_network_fs", TTR("Small Deploy with Network FS")), RUN_FILE_SERVER);
6363 	p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is enabled, export or deploy will produce a minimal executable.\nThe filesystem will be provided from the project by the editor over the network.\nOn Android, deploy will use the USB cable for faster performance. This option speeds up testing for games with a large footprint."));
6364 	p->add_separator();
6365 	p->add_check_shortcut(ED_SHORTCUT("editor/visible_collision_shapes", TTR("Visible Collision Shapes")), RUN_DEBUG_COLLISONS);
6366 	p->set_item_tooltip(p->get_item_count() - 1, TTR("Collision shapes and raycast nodes (for 2D and 3D) will be visible on the running game if this option is turned on."));
6367 	p->add_check_shortcut(ED_SHORTCUT("editor/visible_navigation", TTR("Visible Navigation")), RUN_DEBUG_NAVIGATION);
6368 	p->set_item_tooltip(p->get_item_count() - 1, TTR("Navigation meshes and polygons will be visible on the running game if this option is turned on."));
6369 	p->add_separator();
6370 	p->add_check_shortcut(ED_SHORTCUT("editor/sync_scene_changes", TTR("Sync Scene Changes")), RUN_LIVE_DEBUG);
6371 	p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is turned on, any changes made to the scene in the editor will be replicated in the running game.\nWhen used remotely on a device, this is more efficient with network filesystem."));
6372 	p->add_check_shortcut(ED_SHORTCUT("editor/sync_script_changes", TTR("Sync Script Changes")), RUN_RELOAD_SCRIPTS);
6373 	p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is turned on, any script that is saved will be reloaded on the running game.\nWhen used remotely on a device, this is more efficient with network filesystem."));
6374 	p->connect("id_pressed", this, "_menu_option");
6375 
6376 	menu_hb->add_spacer();
6377 
6378 	settings_menu = memnew(MenuButton);
6379 	settings_menu->set_flat(false);
6380 	settings_menu->set_switch_on_hover(true);
6381 	settings_menu->set_text(TTR("Editor"));
6382 	settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
6383 	left_menu_hb->add_child(settings_menu);
6384 
6385 	p = settings_menu->get_popup();
6386 	p->set_hide_on_window_lose_focus(true);
6387 #ifdef OSX_ENABLED
6388 	p->add_shortcut(ED_SHORTCUT("editor/editor_settings", TTR("Editor Settings..."), KEY_MASK_CMD + KEY_COMMA), SETTINGS_PREFERENCES);
6389 #else
6390 	p->add_shortcut(ED_SHORTCUT("editor/editor_settings", TTR("Editor Settings...")), SETTINGS_PREFERENCES);
6391 #endif
6392 	p->add_separator();
6393 
6394 	editor_layouts = memnew(PopupMenu);
6395 	editor_layouts->set_name("Layouts");
6396 	p->add_child(editor_layouts);
6397 	editor_layouts->connect("id_pressed", this, "_layout_menu_option");
6398 	p->add_submenu_item(TTR("Editor Layout"), "Layouts");
6399 	p->add_separator();
6400 #ifdef OSX_ENABLED
6401 	p->add_shortcut(ED_SHORTCUT("editor/take_screenshot", TTR("Take Screenshot"), KEY_MASK_CMD | KEY_F12), EDITOR_SCREENSHOT);
6402 #else
6403 	p->add_shortcut(ED_SHORTCUT("editor/take_screenshot", TTR("Take Screenshot"), KEY_MASK_CTRL | KEY_F12), EDITOR_SCREENSHOT);
6404 #endif
6405 	p->set_item_tooltip(p->get_item_count() - 1, TTR("Screenshots are stored in the Editor Data/Settings Folder."));
6406 #ifdef OSX_ENABLED
6407 	p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_F), SETTINGS_TOGGLE_FULLSCREEN);
6408 #else
6409 	p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_SHIFT | KEY_F11), SETTINGS_TOGGLE_FULLSCREEN);
6410 #endif
6411 #ifdef WINDOWS_ENABLED
6412 	p->add_item(TTR("Toggle System Console"), SETTINGS_TOGGLE_CONSOLE);
6413 #endif
6414 	p->add_separator();
6415 
6416 	if (OS::get_singleton()->get_data_path() == OS::get_singleton()->get_config_path()) {
6417 		// Configuration and data folders are located in the same place (Windows/macOS)
6418 		p->add_item(TTR("Open Editor Data/Settings Folder"), SETTINGS_EDITOR_DATA_FOLDER);
6419 	} else {
6420 		// Separate configuration and data folders (Linux)
6421 		p->add_item(TTR("Open Editor Data Folder"), SETTINGS_EDITOR_DATA_FOLDER);
6422 		p->add_item(TTR("Open Editor Settings Folder"), SETTINGS_EDITOR_CONFIG_FOLDER);
6423 	}
6424 	p->add_separator();
6425 
6426 	p->add_item(TTR("Manage Editor Features..."), SETTINGS_MANAGE_FEATURE_PROFILES);
6427 	p->add_item(TTR("Manage Export Templates..."), SETTINGS_MANAGE_EXPORT_TEMPLATES);
6428 
6429 	// Help Menu
6430 	help_menu = memnew(MenuButton);
6431 	help_menu->set_flat(false);
6432 	help_menu->set_switch_on_hover(true);
6433 	help_menu->set_text(TTR("Help"));
6434 	help_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
6435 	left_menu_hb->add_child(help_menu);
6436 
6437 	p = help_menu->get_popup();
6438 	p->set_hide_on_window_lose_focus(true);
6439 	p->connect("id_pressed", this, "_menu_option");
6440 	p->add_icon_shortcut(gui_base->get_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("editor/editor_help", TTR("Search"), KEY_MASK_SHIFT | KEY_F1), HELP_SEARCH);
6441 	p->add_separator();
6442 	p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/online_docs", TTR("Online Docs")), HELP_DOCS);
6443 	p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/q&a", TTR("Q&A")), HELP_QA);
6444 	p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG);
6445 	p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK);
6446 	p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/community", TTR("Community")), HELP_COMMUNITY);
6447 	p->add_separator();
6448 	p->add_icon_shortcut(gui_base->get_icon("Godot", "EditorIcons"), ED_SHORTCUT("editor/about", TTR("About")), HELP_ABOUT);
6449 
6450 	HBoxContainer *play_hb = memnew(HBoxContainer);
6451 	menu_hb->add_child(play_hb);
6452 
6453 	play_button = memnew(ToolButton);
6454 	play_hb->add_child(play_button);
6455 	play_button->set_toggle_mode(true);
6456 	play_button->set_icon(gui_base->get_icon("MainPlay", "EditorIcons"));
6457 	play_button->set_focus_mode(Control::FOCUS_NONE);
6458 	play_button->connect("pressed", this, "_menu_option", make_binds(RUN_PLAY));
6459 	play_button->set_tooltip(TTR("Play the project."));
6460 #ifdef OSX_ENABLED
6461 	play_button->set_shortcut(ED_SHORTCUT("editor/play", TTR("Play"), KEY_MASK_CMD | KEY_B));
6462 #else
6463 	play_button->set_shortcut(ED_SHORTCUT("editor/play", TTR("Play"), KEY_F5));
6464 #endif
6465 
6466 	pause_button = memnew(ToolButton);
6467 	pause_button->set_toggle_mode(true);
6468 	pause_button->set_icon(gui_base->get_icon("Pause", "EditorIcons"));
6469 	pause_button->set_focus_mode(Control::FOCUS_NONE);
6470 	pause_button->set_tooltip(TTR("Pause the scene execution for debugging."));
6471 	pause_button->set_disabled(true);
6472 	play_hb->add_child(pause_button);
6473 #ifdef OSX_ENABLED
6474 	pause_button->set_shortcut(ED_SHORTCUT("editor/pause_scene", TTR("Pause Scene"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_Y));
6475 #else
6476 	pause_button->set_shortcut(ED_SHORTCUT("editor/pause_scene", TTR("Pause Scene"), KEY_F7));
6477 #endif
6478 
6479 	stop_button = memnew(ToolButton);
6480 	play_hb->add_child(stop_button);
6481 	stop_button->set_focus_mode(Control::FOCUS_NONE);
6482 	stop_button->set_icon(gui_base->get_icon("Stop", "EditorIcons"));
6483 	stop_button->connect("pressed", this, "_menu_option", make_binds(RUN_STOP));
6484 	stop_button->set_tooltip(TTR("Stop the scene."));
6485 	stop_button->set_disabled(true);
6486 #ifdef OSX_ENABLED
6487 	stop_button->set_shortcut(ED_SHORTCUT("editor/stop", TTR("Stop"), KEY_MASK_CMD | KEY_PERIOD));
6488 #else
6489 	stop_button->set_shortcut(ED_SHORTCUT("editor/stop", TTR("Stop"), KEY_F8));
6490 #endif
6491 
6492 	run_native = memnew(EditorRunNative);
6493 	play_hb->add_child(run_native);
6494 	run_native->connect("native_run", this, "_menu_option", varray(RUN_PLAY_NATIVE));
6495 
6496 	play_scene_button = memnew(ToolButton);
6497 	play_hb->add_child(play_scene_button);
6498 	play_scene_button->set_toggle_mode(true);
6499 	play_scene_button->set_focus_mode(Control::FOCUS_NONE);
6500 	play_scene_button->set_icon(gui_base->get_icon("PlayScene", "EditorIcons"));
6501 	play_scene_button->connect("pressed", this, "_menu_option", make_binds(RUN_PLAY_SCENE));
6502 	play_scene_button->set_tooltip(TTR("Play the edited scene."));
6503 #ifdef OSX_ENABLED
6504 	play_scene_button->set_shortcut(ED_SHORTCUT("editor/play_scene", TTR("Play Scene"), KEY_MASK_CMD | KEY_R));
6505 #else
6506 	play_scene_button->set_shortcut(ED_SHORTCUT("editor/play_scene", TTR("Play Scene"), KEY_F6));
6507 #endif
6508 
6509 	play_custom_scene_button = memnew(ToolButton);
6510 	play_hb->add_child(play_custom_scene_button);
6511 	play_custom_scene_button->set_toggle_mode(true);
6512 	play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE);
6513 	play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom", "EditorIcons"));
6514 	play_custom_scene_button->connect("pressed", this, "_menu_option", make_binds(RUN_PLAY_CUSTOM_SCENE));
6515 	play_custom_scene_button->set_tooltip(TTR("Play custom scene"));
6516 #ifdef OSX_ENABLED
6517 	play_custom_scene_button->set_shortcut(ED_SHORTCUT("editor/play_custom_scene", TTR("Play Custom Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R));
6518 #else
6519 	play_custom_scene_button->set_shortcut(ED_SHORTCUT("editor/play_custom_scene", TTR("Play Custom Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F5));
6520 #endif
6521 
6522 	HBoxContainer *right_menu_hb = memnew(HBoxContainer);
6523 	menu_hb->add_child(right_menu_hb);
6524 
6525 	// Toggle for video driver
6526 	video_driver = memnew(OptionButton);
6527 	video_driver->set_flat(true);
6528 	video_driver->set_focus_mode(Control::FOCUS_NONE);
6529 	video_driver->connect("item_selected", this, "_video_driver_selected");
6530 	video_driver->add_font_override("font", gui_base->get_font("bold", "EditorFonts"));
6531 	right_menu_hb->add_child(video_driver);
6532 
6533 	String video_drivers = ProjectSettings::get_singleton()->get_custom_property_info()["rendering/quality/driver/driver_name"].hint_string;
6534 	String current_video_driver = OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver());
6535 	video_driver_current = 0;
6536 	for (int i = 0; i < video_drivers.get_slice_count(","); i++) {
6537 		String driver = video_drivers.get_slice(",", i);
6538 		video_driver->add_item(driver);
6539 		video_driver->set_item_metadata(i, driver);
6540 
6541 		if (current_video_driver == driver) {
6542 			video_driver->select(i);
6543 			video_driver_current = i;
6544 		}
6545 	}
6546 
6547 	_update_video_driver_color();
6548 
6549 	video_restart_dialog = memnew(ConfirmationDialog);
6550 	video_restart_dialog->set_text(TTR("Changing the video driver requires restarting the editor."));
6551 	video_restart_dialog->get_ok()->set_text(TTR("Save & Restart"));
6552 	video_restart_dialog->connect("confirmed", this, "_menu_option", varray(SET_VIDEO_DRIVER_SAVE_AND_RESTART));
6553 	gui_base->add_child(video_restart_dialog);
6554 
6555 	progress_hb = memnew(BackgroundProgress);
6556 
6557 	layout_dialog = memnew(EditorLayoutsDialog);
6558 	gui_base->add_child(layout_dialog);
6559 	layout_dialog->set_hide_on_ok(false);
6560 	layout_dialog->set_size(Size2(225, 270) * EDSCALE);
6561 	layout_dialog->connect("name_confirmed", this, "_dialog_action");
6562 
6563 	update_spinner = memnew(MenuButton);
6564 	update_spinner->set_tooltip(TTR("Spins when the editor window redraws."));
6565 	right_menu_hb->add_child(update_spinner);
6566 	update_spinner->set_icon(gui_base->get_icon("Progress1", "EditorIcons"));
6567 	update_spinner->get_popup()->connect("id_pressed", this, "_menu_option");
6568 	p = update_spinner->get_popup();
6569 	p->add_radio_check_item(TTR("Update Continuously"), SETTINGS_UPDATE_CONTINUOUSLY);
6570 	p->add_radio_check_item(TTR("Update When Changed"), SETTINGS_UPDATE_WHEN_CHANGED);
6571 	p->add_separator();
6572 	p->add_item(TTR("Hide Update Spinner"), SETTINGS_UPDATE_SPINNER_HIDE);
6573 	_update_update_spinner();
6574 
6575 	// Instantiate and place editor docks
6576 
6577 	scene_tree_dock = memnew(SceneTreeDock(this, scene_root, editor_selection, editor_data));
6578 	inspector_dock = memnew(InspectorDock(this, editor_data));
6579 	import_dock = memnew(ImportDock);
6580 	node_dock = memnew(NodeDock);
6581 
6582 	filesystem_dock = memnew(FileSystemDock(this));
6583 	filesystem_dock->connect("inherit", this, "_inherit_request");
6584 	filesystem_dock->connect("instance", this, "_instance_request");
6585 	filesystem_dock->connect("display_mode_changed", this, "_save_docks");
6586 
6587 	// Scene: Top left
6588 	dock_slot[DOCK_SLOT_LEFT_UR]->add_child(scene_tree_dock);
6589 	dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(scene_tree_dock->get_index(), TTR("Scene"));
6590 
6591 	// Import: Top left, behind Scene
6592 	dock_slot[DOCK_SLOT_LEFT_UR]->add_child(import_dock);
6593 	dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(import_dock->get_index(), TTR("Import"));
6594 
6595 	// FileSystem: Bottom left
6596 	dock_slot[DOCK_SLOT_LEFT_BR]->add_child(filesystem_dock);
6597 	dock_slot[DOCK_SLOT_LEFT_BR]->set_tab_title(filesystem_dock->get_index(), TTR("FileSystem"));
6598 
6599 	// Inspector: Full height right
6600 	dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(inspector_dock);
6601 	dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(inspector_dock->get_index(), TTR("Inspector"));
6602 
6603 	// Node: Full height right, behind Inspector
6604 	dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(node_dock);
6605 	dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(node_dock->get_index(), TTR("Node"));
6606 
6607 	// Hide unused dock slots and vsplits
6608 	dock_slot[DOCK_SLOT_LEFT_UL]->hide();
6609 	dock_slot[DOCK_SLOT_LEFT_BL]->hide();
6610 	dock_slot[DOCK_SLOT_RIGHT_BL]->hide();
6611 	dock_slot[DOCK_SLOT_RIGHT_UR]->hide();
6612 	dock_slot[DOCK_SLOT_RIGHT_BR]->hide();
6613 	left_l_vsplit->hide();
6614 	right_r_vsplit->hide();
6615 
6616 	// Add some offsets to left_r and main hsplits to make LEFT_R and RIGHT_L docks wider than minsize
6617 	left_r_hsplit->set_split_offset(70 * EDSCALE);
6618 	main_hsplit->set_split_offset(-70 * EDSCALE);
6619 
6620 	// Define corresponding default layout
6621 
6622 	const String docks_section = "docks";
6623 	overridden_default_layout = -1;
6624 	default_layout.instance();
6625 	// Dock numbers are based on DockSlot enum value + 1
6626 	default_layout->set_value(docks_section, "dock_3", "Scene,Import");
6627 	default_layout->set_value(docks_section, "dock_4", "FileSystem");
6628 	default_layout->set_value(docks_section, "dock_5", "Inspector,Node");
6629 
6630 	for (int i = 0; i < vsplits.size(); i++)
6631 		default_layout->set_value(docks_section, "dock_split_" + itos(i + 1), 0);
6632 	default_layout->set_value(docks_section, "dock_hsplit_1", 0);
6633 	default_layout->set_value(docks_section, "dock_hsplit_2", 70 * EDSCALE);
6634 	default_layout->set_value(docks_section, "dock_hsplit_3", -70 * EDSCALE);
6635 	default_layout->set_value(docks_section, "dock_hsplit_4", 0);
6636 
6637 	_update_layouts_menu();
6638 
6639 	// Bottom panels
6640 
6641 	bottom_panel = memnew(PanelContainer);
6642 	bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer"));
6643 	center_split->add_child(bottom_panel);
6644 	center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);
6645 
6646 	bottom_panel_vb = memnew(VBoxContainer);
6647 	bottom_panel->add_child(bottom_panel_vb);
6648 
6649 	bottom_panel_hb = memnew(HBoxContainer);
6650 	bottom_panel_hb->set_custom_minimum_size(Size2(0, 24 * EDSCALE)); // Adjust for the height of the "Expand Bottom Dock" icon.
6651 	bottom_panel_vb->add_child(bottom_panel_hb);
6652 
6653 	bottom_panel_hb_editors = memnew(HBoxContainer);
6654 	bottom_panel_hb_editors->set_h_size_flags(Control::SIZE_EXPAND_FILL);
6655 	bottom_panel_hb->add_child(bottom_panel_hb_editors);
6656 
6657 	version_label = memnew(Label);
6658 	version_label->set_text(VERSION_FULL_CONFIG);
6659 	// Fade out the version label to be less prominent, but still readable
6660 	version_label->set_self_modulate(Color(1, 1, 1, 0.6));
6661 	bottom_panel_hb->add_child(version_label);
6662 
6663 	bottom_panel_raise = memnew(ToolButton);
6664 	bottom_panel_raise->set_icon(gui_base->get_icon("ExpandBottomDock", "EditorIcons"));
6665 
6666 	bottom_panel_raise->set_shortcut(ED_SHORTCUT("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KEY_MASK_SHIFT | KEY_F12));
6667 
6668 	bottom_panel_hb->add_child(bottom_panel_raise);
6669 	bottom_panel_raise->hide();
6670 	bottom_panel_raise->set_toggle_mode(true);
6671 	bottom_panel_raise->connect("toggled", this, "_bottom_panel_raise_toggled");
6672 
6673 	log = memnew(EditorLog);
6674 	ToolButton *output_button = add_bottom_panel_item(TTR("Output"), log);
6675 	log->set_tool_button(output_button);
6676 
6677 	old_split_ofs = 0;
6678 
6679 	center_split->connect("resized", this, "_vp_resized");
6680 
6681 	orphan_resources = memnew(OrphanResourcesDialog);
6682 	gui_base->add_child(orphan_resources);
6683 
6684 	confirmation = memnew(ConfirmationDialog);
6685 	gui_base->add_child(confirmation);
6686 	confirmation->connect("confirmed", this, "_menu_confirm_current");
6687 
6688 	save_confirmation = memnew(ConfirmationDialog);
6689 	save_confirmation->add_button(TTR("Don't Save"), OS::get_singleton()->get_swap_ok_cancel(), "discard");
6690 	gui_base->add_child(save_confirmation);
6691 	save_confirmation->connect("confirmed", this, "_menu_confirm_current");
6692 	save_confirmation->connect("custom_action", this, "_discard_changes");
6693 
6694 	custom_build_manage_templates = memnew(ConfirmationDialog);
6695 	custom_build_manage_templates->set_text(TTR("Android build template is missing, please install relevant templates."));
6696 	custom_build_manage_templates->get_ok()->set_text(TTR("Manage Templates"));
6697 	custom_build_manage_templates->connect("confirmed", this, "_menu_option", varray(SETTINGS_MANAGE_EXPORT_TEMPLATES));
6698 	gui_base->add_child(custom_build_manage_templates);
6699 
6700 	install_android_build_template = memnew(ConfirmationDialog);
6701 	install_android_build_template->set_text(TTR("This will set up your project for custom Android builds by installing the source template to \"res://android/build\".\nYou can then apply modifications and build your own custom APK on export (adding modules, changing the AndroidManifest.xml, etc.).\nNote that in order to make custom builds instead of using pre-built APKs, the \"Use Custom Build\" option should be enabled in the Android export preset."));
6702 	install_android_build_template->get_ok()->set_text(TTR("Install"));
6703 	install_android_build_template->connect("confirmed", this, "_menu_confirm_current");
6704 	gui_base->add_child(install_android_build_template);
6705 
6706 	remove_android_build_template = memnew(ConfirmationDialog);
6707 	remove_android_build_template->set_text(TTR("The Android build template is already installed in this project and it won't be overwritten.\nRemove the \"res://android/build\" directory manually before attempting this operation again."));
6708 	remove_android_build_template->get_ok()->set_text(TTR("Show in File Manager"));
6709 	remove_android_build_template->connect("confirmed", this, "_menu_option", varray(FILE_EXPLORE_ANDROID_BUILD_TEMPLATES));
6710 	gui_base->add_child(remove_android_build_template);
6711 
6712 	file_templates = memnew(EditorFileDialog);
6713 	file_templates->set_title(TTR("Import Templates From ZIP File"));
6714 
6715 	gui_base->add_child(file_templates);
6716 	file_templates->set_mode(EditorFileDialog::MODE_OPEN_FILE);
6717 	file_templates->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
6718 	file_templates->clear_filters();
6719 	file_templates->add_filter("*.tpz ; " + TTR("Template Package"));
6720 
6721 	file = memnew(EditorFileDialog);
6722 	gui_base->add_child(file);
6723 	file->set_current_dir("res://");
6724 
6725 	file_export_lib = memnew(EditorFileDialog);
6726 	file_export_lib->set_title(TTR("Export Library"));
6727 	file_export_lib->set_mode(EditorFileDialog::MODE_SAVE_FILE);
6728 	file_export_lib->connect("file_selected", this, "_dialog_action");
6729 	file_export_lib_merge = memnew(CheckBox);
6730 	file_export_lib_merge->set_text(TTR("Merge With Existing"));
6731 	file_export_lib_merge->set_pressed(true);
6732 	file_export_lib->get_vbox()->add_child(file_export_lib_merge);
6733 	gui_base->add_child(file_export_lib);
6734 
6735 	file_script = memnew(EditorFileDialog);
6736 	file_script->set_title(TTR("Open & Run a Script"));
6737 	file_script->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
6738 	file_script->set_mode(EditorFileDialog::MODE_OPEN_FILE);
6739 	List<String> sexts;
6740 	ResourceLoader::get_recognized_extensions_for_type("Script", &sexts);
6741 	for (List<String>::Element *E = sexts.front(); E; E = E->next()) {
6742 		file_script->add_filter("*." + E->get());
6743 	}
6744 	gui_base->add_child(file_script);
6745 	file_script->connect("file_selected", this, "_dialog_action");
6746 
6747 	file_menu->get_popup()->connect("id_pressed", this, "_menu_option");
6748 	file_menu->connect("about_to_show", this, "_update_file_menu_opened");
6749 	file_menu->get_popup()->connect("popup_hide", this, "_update_file_menu_closed");
6750 
6751 	settings_menu->get_popup()->connect("id_pressed", this, "_menu_option");
6752 
6753 	file->connect("file_selected", this, "_dialog_action");
6754 	file_templates->connect("file_selected", this, "_dialog_action");
6755 
6756 	preview_gen = memnew(AudioStreamPreviewGenerator);
6757 	add_child(preview_gen);
6758 	//plugin stuff
6759 
6760 	file_server = memnew(EditorFileServer);
6761 
6762 	add_editor_plugin(memnew(AnimationPlayerEditorPlugin(this)));
6763 	add_editor_plugin(memnew(CanvasItemEditorPlugin(this)));
6764 	add_editor_plugin(memnew(SpatialEditorPlugin(this)));
6765 	add_editor_plugin(memnew(ScriptEditorPlugin(this)));
6766 
6767 	EditorAudioBuses *audio_bus_editor = EditorAudioBuses::register_editor();
6768 
6769 	ScriptTextEditor::register_editor(); //register one for text scripts
6770 	TextEditor::register_editor();
6771 
6772 	if (StreamPeerSSL::is_available()) {
6773 		add_editor_plugin(memnew(AssetLibraryEditorPlugin(this)));
6774 	} else {
6775 		WARN_PRINT("Asset Library not available, as it requires SSL to work.");
6776 	}
6777 
6778 	//add interface before adding plugins
6779 
6780 	editor_interface = memnew(EditorInterface);
6781 	add_child(editor_interface);
6782 
6783 	//more visually meaningful to have this later
6784 	raise_bottom_panel_item(AnimationPlayerEditor::singleton);
6785 
6786 	add_editor_plugin(VersionControlEditorPlugin::get_singleton());
6787 	add_editor_plugin(memnew(ShaderEditorPlugin(this)));
6788 	add_editor_plugin(memnew(VisualShaderEditorPlugin(this)));
6789 
6790 	add_editor_plugin(memnew(CameraEditorPlugin(this)));
6791 	add_editor_plugin(memnew(ThemeEditorPlugin(this)));
6792 	add_editor_plugin(memnew(MultiMeshEditorPlugin(this)));
6793 	add_editor_plugin(memnew(MeshInstanceEditorPlugin(this)));
6794 	add_editor_plugin(memnew(AnimationTreeEditorPlugin(this)));
6795 	add_editor_plugin(memnew(AnimationTreePlayerEditorPlugin(this)));
6796 	add_editor_plugin(memnew(MeshLibraryEditorPlugin(this)));
6797 	add_editor_plugin(memnew(StyleBoxEditorPlugin(this)));
6798 	add_editor_plugin(memnew(SpriteEditorPlugin(this)));
6799 	add_editor_plugin(memnew(Skeleton2DEditorPlugin(this)));
6800 	add_editor_plugin(memnew(ParticlesEditorPlugin(this)));
6801 	add_editor_plugin(memnew(CPUParticles2DEditorPlugin(this)));
6802 	add_editor_plugin(memnew(CPUParticlesEditorPlugin(this)));
6803 	add_editor_plugin(memnew(ResourcePreloaderEditorPlugin(this)));
6804 	add_editor_plugin(memnew(ItemListEditorPlugin(this)));
6805 	add_editor_plugin(memnew(Polygon3DEditorPlugin(this)));
6806 	add_editor_plugin(memnew(CollisionPolygon2DEditorPlugin(this)));
6807 	add_editor_plugin(memnew(TileSetEditorPlugin(this)));
6808 	add_editor_plugin(memnew(TileMapEditorPlugin(this)));
6809 	add_editor_plugin(memnew(SpriteFramesEditorPlugin(this)));
6810 	add_editor_plugin(memnew(TextureRegionEditorPlugin(this)));
6811 	add_editor_plugin(memnew(Particles2DEditorPlugin(this)));
6812 	add_editor_plugin(memnew(GIProbeEditorPlugin(this)));
6813 	add_editor_plugin(memnew(BakedLightmapEditorPlugin(this)));
6814 	add_editor_plugin(memnew(Path2DEditorPlugin(this)));
6815 	add_editor_plugin(memnew(PathEditorPlugin(this)));
6816 	add_editor_plugin(memnew(Line2DEditorPlugin(this)));
6817 	add_editor_plugin(memnew(Polygon2DEditorPlugin(this)));
6818 	add_editor_plugin(memnew(LightOccluder2DEditorPlugin(this)));
6819 	add_editor_plugin(memnew(NavigationPolygonEditorPlugin(this)));
6820 	add_editor_plugin(memnew(GradientEditorPlugin(this)));
6821 	add_editor_plugin(memnew(CollisionShape2DEditorPlugin(this)));
6822 	add_editor_plugin(memnew(CurveEditorPlugin(this)));
6823 	add_editor_plugin(memnew(TextureEditorPlugin(this)));
6824 	add_editor_plugin(memnew(AudioStreamEditorPlugin(this)));
6825 	add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor)));
6826 	add_editor_plugin(memnew(SkeletonEditorPlugin(this)));
6827 	add_editor_plugin(memnew(SkeletonIKEditorPlugin(this)));
6828 	add_editor_plugin(memnew(PhysicalBonePlugin(this)));
6829 	add_editor_plugin(memnew(MeshEditorPlugin(this)));
6830 	add_editor_plugin(memnew(MaterialEditorPlugin(this)));
6831 
6832 	for (int i = 0; i < EditorPlugins::get_plugin_count(); i++)
6833 		add_editor_plugin(EditorPlugins::create(i, this));
6834 
6835 	for (int i = 0; i < plugin_init_callback_count; i++) {
6836 		plugin_init_callbacks[i]();
6837 	}
6838 
6839 	resource_preview->add_preview_generator(Ref<EditorTexturePreviewPlugin>(memnew(EditorTexturePreviewPlugin)));
6840 	resource_preview->add_preview_generator(Ref<EditorImagePreviewPlugin>(memnew(EditorImagePreviewPlugin)));
6841 	resource_preview->add_preview_generator(Ref<EditorPackedScenePreviewPlugin>(memnew(EditorPackedScenePreviewPlugin)));
6842 	resource_preview->add_preview_generator(Ref<EditorMaterialPreviewPlugin>(memnew(EditorMaterialPreviewPlugin)));
6843 	resource_preview->add_preview_generator(Ref<EditorScriptPreviewPlugin>(memnew(EditorScriptPreviewPlugin)));
6844 	resource_preview->add_preview_generator(Ref<EditorAudioStreamPreviewPlugin>(memnew(EditorAudioStreamPreviewPlugin)));
6845 	resource_preview->add_preview_generator(Ref<EditorMeshPreviewPlugin>(memnew(EditorMeshPreviewPlugin)));
6846 	resource_preview->add_preview_generator(Ref<EditorBitmapPreviewPlugin>(memnew(EditorBitmapPreviewPlugin)));
6847 	resource_preview->add_preview_generator(Ref<EditorFontPreviewPlugin>(memnew(EditorFontPreviewPlugin)));
6848 
6849 	{
6850 		Ref<SpatialMaterialConversionPlugin> spatial_mat_convert;
6851 		spatial_mat_convert.instance();
6852 		resource_conversion_plugins.push_back(spatial_mat_convert);
6853 
6854 		Ref<CanvasItemMaterialConversionPlugin> canvas_item_mat_convert;
6855 		canvas_item_mat_convert.instance();
6856 		resource_conversion_plugins.push_back(canvas_item_mat_convert);
6857 
6858 		Ref<ParticlesMaterialConversionPlugin> particles_mat_convert;
6859 		particles_mat_convert.instance();
6860 		resource_conversion_plugins.push_back(particles_mat_convert);
6861 
6862 		Ref<VisualShaderConversionPlugin> vshader_convert;
6863 		vshader_convert.instance();
6864 		resource_conversion_plugins.push_back(vshader_convert);
6865 	}
6866 	update_spinner_step_msec = OS::get_singleton()->get_ticks_msec();
6867 	update_spinner_step_frame = Engine::get_singleton()->get_frames_drawn();
6868 	update_spinner_step = 0;
6869 
6870 	editor_plugin_screen = NULL;
6871 	editor_plugins_over = memnew(EditorPluginList);
6872 	editor_plugins_force_over = memnew(EditorPluginList);
6873 	editor_plugins_force_input_forwarding = memnew(EditorPluginList);
6874 
6875 	Ref<EditorExportTextSceneToBinaryPlugin> export_text_to_binary_plugin;
6876 	export_text_to_binary_plugin.instance();
6877 
6878 	EditorExport::get_singleton()->add_export_plugin(export_text_to_binary_plugin);
6879 
6880 	_edit_current();
6881 	current = NULL;
6882 	saving_resource = Ref<Resource>();
6883 
6884 	reference_resource_mem = true;
6885 	save_external_resources_mem = true;
6886 
6887 	set_process(true);
6888 
6889 	open_imported = memnew(ConfirmationDialog);
6890 	open_imported->get_ok()->set_text(TTR("Open Anyway"));
6891 	new_inherited_button = open_imported->add_button(TTR("New Inherited"), !OS::get_singleton()->get_swap_ok_cancel(), "inherit");
6892 	open_imported->connect("confirmed", this, "_open_imported");
6893 	open_imported->connect("custom_action", this, "_inherit_imported");
6894 	gui_base->add_child(open_imported);
6895 
6896 	saved_version = 1;
6897 	unsaved_cache = true;
6898 	_last_instanced_scene = NULL;
6899 
6900 	quick_open = memnew(EditorQuickOpen);
6901 	gui_base->add_child(quick_open);
6902 	quick_open->connect("quick_open", this, "_quick_opened");
6903 
6904 	quick_run = memnew(EditorQuickOpen);
6905 	gui_base->add_child(quick_run);
6906 	quick_run->connect("quick_open", this, "_quick_run");
6907 
6908 	_update_recent_scenes();
6909 
6910 	editor_data.restore_editor_global_states();
6911 	convert_old = false;
6912 	opening_prev = false;
6913 	set_process_unhandled_input(true);
6914 	_playing_edited = false;
6915 
6916 	load_errors = memnew(RichTextLabel);
6917 	load_error_dialog = memnew(AcceptDialog);
6918 	load_error_dialog->add_child(load_errors);
6919 	load_error_dialog->set_title(TTR("Load Errors"));
6920 	gui_base->add_child(load_error_dialog);
6921 
6922 	execute_outputs = memnew(RichTextLabel);
6923 	execute_outputs->set_selection_enabled(true);
6924 	execute_output_dialog = memnew(AcceptDialog);
6925 	execute_output_dialog->add_child(execute_outputs);
6926 	execute_output_dialog->set_title("");
6927 	gui_base->add_child(execute_output_dialog);
6928 
6929 	EditorFileSystem::get_singleton()->connect("sources_changed", this, "_sources_changed");
6930 	EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_fs_changed");
6931 	EditorFileSystem::get_singleton()->connect("resources_reimported", this, "_resources_reimported");
6932 	EditorFileSystem::get_singleton()->connect("resources_reload", this, "_resources_changed");
6933 
6934 	_build_icon_type_cache();
6935 
6936 	Node::set_human_readable_collision_renaming(true);
6937 
6938 	pick_main_scene = memnew(ConfirmationDialog);
6939 	gui_base->add_child(pick_main_scene);
6940 	pick_main_scene->get_ok()->set_text(TTR("Select"));
6941 	pick_main_scene->connect("confirmed", this, "_menu_option", varray(SETTINGS_PICK_MAIN_SCENE));
6942 
6943 	for (int i = 0; i < _init_callbacks.size(); i++)
6944 		_init_callbacks[i]();
6945 
6946 	editor_data.add_edited_scene(-1);
6947 	editor_data.set_edited_scene(0);
6948 	_update_scene_tabs();
6949 
6950 	import_dock->initialize_import_options();
6951 
6952 	FileAccess::set_file_close_fail_notify_callback(_file_access_close_error_notify);
6953 
6954 	waiting_for_first_scan = true;
6955 
6956 	print_handler.printfunc = _print_handler;
6957 	print_handler.userdata = this;
6958 	add_print_handler(&print_handler);
6959 
6960 	ResourceSaver::set_save_callback(_resource_saved);
6961 	ResourceLoader::set_load_callback(_resource_loaded);
6962 
6963 #ifdef OSX_ENABLED
6964 	ED_SHORTCUT("editor/editor_2d", TTR("Open 2D Editor"), KEY_MASK_ALT | KEY_1);
6965 	ED_SHORTCUT("editor/editor_3d", TTR("Open 3D Editor"), KEY_MASK_ALT | KEY_2);
6966 	ED_SHORTCUT("editor/editor_script", TTR("Open Script Editor"), KEY_MASK_ALT | KEY_3);
6967 	ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_MASK_ALT | KEY_SPACE);
6968 #else
6969 	ED_SHORTCUT("editor/editor_2d", TTR("Open 2D Editor"), KEY_F1);
6970 	ED_SHORTCUT("editor/editor_3d", TTR("Open 3D Editor"), KEY_F2);
6971 	ED_SHORTCUT("editor/editor_script", TTR("Open Script Editor"), KEY_F3); //hack needed for script editor F3 search to work :) Assign like this or don't use F3
6972 	ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_MASK_SHIFT | KEY_F1);
6973 #endif
6974 	ED_SHORTCUT("editor/editor_assetlib", TTR("Open Asset Library"));
6975 	ED_SHORTCUT("editor/editor_next", TTR("Open the next Editor"));
6976 	ED_SHORTCUT("editor/editor_prev", TTR("Open the previous Editor"));
6977 
6978 	screenshot_timer = memnew(Timer);
6979 	screenshot_timer->set_one_shot(true);
6980 	screenshot_timer->set_wait_time(settings_menu->get_popup()->get_submenu_popup_delay() + 0.1f);
6981 	screenshot_timer->connect("timeout", this, "_request_screenshot");
6982 	add_child(screenshot_timer);
6983 	screenshot_timer->set_owner(get_owner());
6984 
6985 	String exec = OS::get_singleton()->get_executable_path();
6986 	EditorSettings::get_singleton()->set_project_metadata("editor_metadata", "executable_path", exec); // Save editor executable path for third-party tools
6987 }
6988 
~EditorNode()6989 EditorNode::~EditorNode() {
6990 
6991 	EditorInspector::cleanup_plugins();
6992 
6993 	remove_print_handler(&print_handler);
6994 	memdelete(EditorHelp::get_doc_data());
6995 	memdelete(editor_selection);
6996 	memdelete(editor_plugins_over);
6997 	memdelete(editor_plugins_force_over);
6998 	memdelete(editor_plugins_force_input_forwarding);
6999 	memdelete(file_server);
7000 	memdelete(progress_hb);
7001 
7002 	EditorSettings::destroy();
7003 }
7004 
7005 /*
7006  * EDITOR PLUGIN LIST
7007  */
7008 
make_visible(bool p_visible)7009 void EditorPluginList::make_visible(bool p_visible) {
7010 
7011 	for (int i = 0; i < plugins_list.size(); i++) {
7012 		plugins_list[i]->make_visible(p_visible);
7013 	}
7014 }
7015 
edit(Object * p_object)7016 void EditorPluginList::edit(Object *p_object) {
7017 
7018 	for (int i = 0; i < plugins_list.size(); i++) {
7019 		plugins_list[i]->edit(p_object);
7020 	}
7021 }
7022 
forward_gui_input(const Ref<InputEvent> & p_event)7023 bool EditorPluginList::forward_gui_input(const Ref<InputEvent> &p_event) {
7024 
7025 	bool discard = false;
7026 
7027 	for (int i = 0; i < plugins_list.size(); i++) {
7028 		if (plugins_list[i]->forward_canvas_gui_input(p_event)) {
7029 			discard = true;
7030 		}
7031 	}
7032 
7033 	return discard;
7034 }
7035 
forward_spatial_gui_input(Camera * p_camera,const Ref<InputEvent> & p_event,bool serve_when_force_input_enabled)7036 bool EditorPluginList::forward_spatial_gui_input(Camera *p_camera, const Ref<InputEvent> &p_event, bool serve_when_force_input_enabled) {
7037 	bool discard = false;
7038 
7039 	for (int i = 0; i < plugins_list.size(); i++) {
7040 		if ((!serve_when_force_input_enabled) && plugins_list[i]->is_input_event_forwarding_always_enabled()) {
7041 			continue;
7042 		}
7043 
7044 		if (plugins_list[i]->forward_spatial_gui_input(p_camera, p_event)) {
7045 			discard = true;
7046 		}
7047 	}
7048 
7049 	return discard;
7050 }
7051 
forward_canvas_draw_over_viewport(Control * p_overlay)7052 void EditorPluginList::forward_canvas_draw_over_viewport(Control *p_overlay) {
7053 
7054 	for (int i = 0; i < plugins_list.size(); i++) {
7055 		plugins_list[i]->forward_canvas_draw_over_viewport(p_overlay);
7056 	}
7057 }
7058 
forward_canvas_force_draw_over_viewport(Control * p_overlay)7059 void EditorPluginList::forward_canvas_force_draw_over_viewport(Control *p_overlay) {
7060 
7061 	for (int i = 0; i < plugins_list.size(); i++) {
7062 		plugins_list[i]->forward_canvas_force_draw_over_viewport(p_overlay);
7063 	}
7064 }
7065 
forward_spatial_draw_over_viewport(Control * p_overlay)7066 void EditorPluginList::forward_spatial_draw_over_viewport(Control *p_overlay) {
7067 
7068 	for (int i = 0; i < plugins_list.size(); i++) {
7069 		plugins_list[i]->forward_spatial_draw_over_viewport(p_overlay);
7070 	}
7071 }
7072 
forward_spatial_force_draw_over_viewport(Control * p_overlay)7073 void EditorPluginList::forward_spatial_force_draw_over_viewport(Control *p_overlay) {
7074 
7075 	for (int i = 0; i < plugins_list.size(); i++) {
7076 		plugins_list[i]->forward_spatial_force_draw_over_viewport(p_overlay);
7077 	}
7078 }
7079 
add_plugin(EditorPlugin * p_plugin)7080 void EditorPluginList::add_plugin(EditorPlugin *p_plugin) {
7081 	plugins_list.push_back(p_plugin);
7082 }
7083 
remove_plugin(EditorPlugin * p_plugin)7084 void EditorPluginList::remove_plugin(EditorPlugin *p_plugin) {
7085 	plugins_list.erase(p_plugin);
7086 }
7087 
empty()7088 bool EditorPluginList::empty() {
7089 	return plugins_list.empty();
7090 }
7091 
clear()7092 void EditorPluginList::clear() {
7093 	plugins_list.clear();
7094 }
7095 
EditorPluginList()7096 EditorPluginList::EditorPluginList() {
7097 }
7098 
~EditorPluginList()7099 EditorPluginList::~EditorPluginList() {
7100 }
7101