2023-01-10 15:26:54 +01:00
/**************************************************************************/
/* editor_node.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-05 00:50:27 +01:00
2014-02-10 02:10:30 +01:00
# include "editor_node.h"
2017-01-16 08:04:19 +01:00
2017-08-26 17:46:49 +02:00
# include "core/bind/core_bind.h"
# include "core/class_db.h"
# include "core/io/config_file.h"
2019-10-23 20:11:04 +02:00
# include "core/io/image_loader.h"
2014-02-10 02:10:30 +01:00
# include "core/io/resource_loader.h"
2017-03-05 16:44:50 +01:00
# include "core/io/resource_saver.h"
2017-08-26 17:46:49 +02:00
# include "core/io/stream_peer_ssl.h"
# include "core/message_queue.h"
# include "core/os/file_access.h"
# include "core/os/input.h"
# include "core/os/keyboard.h"
# include "core/os/os.h"
# include "core/path_remap.h"
# include "core/print_string.h"
# include "core/project_settings.h"
# include "core/translation.h"
# include "core/version.h"
2017-03-05 16:44:50 +01:00
# include "main/input_default.h"
2019-04-07 20:46:52 +02:00
# include "main/main.h"
2019-12-24 08:17:23 +01:00
# include "scene/gui/center_container.h"
# include "scene/gui/control.h"
# include "scene/gui/dialogs.h"
# include "scene/gui/file_dialog.h"
2019-12-24 01:20:54 +01:00
# include "scene/gui/link_button.h"
2019-12-24 08:17:23 +01:00
# include "scene/gui/menu_button.h"
# include "scene/gui/panel.h"
# include "scene/gui/panel_container.h"
# include "scene/gui/split_container.h"
# include "scene/gui/tab_container.h"
# include "scene/gui/tabs.h"
# include "scene/gui/texture_progress.h"
# include "scene/gui/tool_button.h"
2017-03-05 16:44:50 +01:00
# include "scene/resources/packed_scene.h"
2021-12-16 06:15:23 +01:00
# include "servers/navigation_2d_server.h"
# include "servers/navigation_server.h"
2017-03-05 16:44:50 +01:00
# include "servers/physics_2d_server.h"
2017-08-26 17:46:49 +02:00
2019-12-24 08:17:23 +01:00
# include "editor/audio_stream_preview.h"
# include "editor/dependency_editor.h"
# include "editor/editor_about.h"
2017-08-26 17:46:49 +02:00
# include "editor/editor_audio_buses.h"
2019-12-24 08:17:23 +01:00
# include "editor/editor_export.h"
# include "editor/editor_feature_profile.h"
2017-08-26 17:46:49 +02:00
# include "editor/editor_file_system.h"
# include "editor/editor_help.h"
2019-12-24 08:17:23 +01:00
# include "editor/editor_inspector.h"
# include "editor/editor_layouts_dialog.h"
# include "editor/editor_log.h"
# include "editor/editor_plugin.h"
2018-05-15 22:12:35 +02:00
# include "editor/editor_properties.h"
2022-02-28 13:06:31 +01:00
# include "editor/editor_property_name_processor.h"
2022-07-25 12:33:41 +02:00
# include "editor/editor_quick_open.h"
2021-06-10 18:07:48 +02:00
# include "editor/editor_resource_picker.h"
2019-12-24 08:17:23 +01:00
# include "editor/editor_resource_preview.h"
# include "editor/editor_run_native.h"
# include "editor/editor_run_script.h"
# include "editor/editor_scale.h"
2017-08-26 17:46:49 +02:00
# include "editor/editor_settings.h"
2019-10-20 17:43:14 +02:00
# include "editor/editor_spin_slider.h"
2017-08-26 17:46:49 +02:00
# include "editor/editor_themes.h"
2019-12-24 08:17:23 +01:00
# include "editor/export_template_manager.h"
# include "editor/fileserver/editor_file_server.h"
# include "editor/filesystem_dock.h"
2017-08-26 17:46:49 +02:00
# include "editor/import/editor_import_collada.h"
2018-01-06 20:36:49 +01:00
# include "editor/import/resource_importer_bitmask.h"
2017-08-26 17:46:49 +02:00
# include "editor/import/resource_importer_csv_translation.h"
2018-07-29 21:45:23 +02:00
# include "editor/import/resource_importer_image.h"
2018-08-06 19:56:06 +02:00
# include "editor/import/resource_importer_layered_texture.h"
2017-08-26 17:46:49 +02:00
# include "editor/import/resource_importer_obj.h"
# include "editor/import/resource_importer_scene.h"
# include "editor/import/resource_importer_texture.h"
2019-04-19 20:54:33 +02:00
# include "editor/import/resource_importer_texture_atlas.h"
2017-08-26 17:46:49 +02:00
# include "editor/import/resource_importer_wav.h"
2019-12-24 08:17:23 +01:00
# include "editor/import_dock.h"
2019-11-10 09:37:51 +01:00
# include "editor/multi_node_edit.h"
2019-12-24 08:17:23 +01:00
# include "editor/node_dock.h"
# include "editor/pane_drag.h"
# include "editor/plugin_config_dialog.h"
2018-06-22 21:52:13 +02:00
# include "editor/plugins/animation_blend_space_1d_editor.h"
# include "editor/plugins/animation_blend_space_2d_editor.h"
2018-06-19 03:10:48 +02:00
# include "editor/plugins/animation_blend_tree_editor_plugin.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/animation_player_editor_plugin.h"
2018-06-25 21:21:57 +02:00
# include "editor/plugins/animation_state_machine_editor.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/animation_tree_editor_plugin.h"
2018-08-20 18:38:18 +02:00
# include "editor/plugins/animation_tree_player_editor_plugin.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/asset_library_editor_plugin.h"
2018-07-16 09:30:27 +02:00
# include "editor/plugins/audio_stream_editor_plugin.h"
2017-12-14 12:59:46 +01:00
# include "editor/plugins/baked_lightmap_editor_plugin.h"
2022-03-31 03:25:14 +02:00
# include "editor/plugins/bit_map_editor_plugin.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/camera_editor_plugin.h"
# include "editor/plugins/canvas_item_editor_plugin.h"
# include "editor/plugins/collision_polygon_2d_editor_plugin.h"
# include "editor/plugins/collision_polygon_editor_plugin.h"
# include "editor/plugins/collision_shape_2d_editor_plugin.h"
2019-03-19 17:28:57 +01:00
# include "editor/plugins/cpu_particles_2d_editor_plugin.h"
2018-07-07 01:21:13 +02:00
# include "editor/plugins/cpu_particles_editor_plugin.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/curve_editor_plugin.h"
# include "editor/plugins/editor_preview_plugins.h"
# include "editor/plugins/gi_probe_editor_plugin.h"
# include "editor/plugins/gradient_editor_plugin.h"
2022-03-18 05:50:34 +01:00
# include "editor/plugins/gradient_texture_2d_editor_plugin.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/item_list_editor_plugin.h"
# include "editor/plugins/light_occluder_2d_editor_plugin.h"
# include "editor/plugins/line_2d_editor_plugin.h"
# include "editor/plugins/material_editor_plugin.h"
# include "editor/plugins/mesh_editor_plugin.h"
# include "editor/plugins/mesh_instance_editor_plugin.h"
2018-08-22 00:06:52 +02:00
# include "editor/plugins/mesh_library_editor_plugin.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/multimesh_editor_plugin.h"
# include "editor/plugins/navigation_polygon_editor_plugin.h"
2022-12-12 04:38:08 +01:00
# include "editor/plugins/packed_scene_editor_plugin.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/particles_2d_editor_plugin.h"
# include "editor/plugins/particles_editor_plugin.h"
# include "editor/plugins/path_2d_editor_plugin.h"
# include "editor/plugins/path_editor_plugin.h"
2017-10-03 18:49:32 +02:00
# include "editor/plugins/physical_bone_plugin.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/polygon_2d_editor_plugin.h"
2022-03-20 04:20:01 +01:00
# include "editor/plugins/ray_cast_2d_editor_plugin.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/resource_preloader_editor_plugin.h"
2021-02-04 11:43:08 +01:00
# include "editor/plugins/room_manager_editor_plugin.h"
2018-06-27 00:05:11 +02:00
# include "editor/plugins/root_motion_editor_plugin.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/script_editor_plugin.h"
# include "editor/plugins/script_text_editor.h"
# include "editor/plugins/shader_editor_plugin.h"
2018-02-21 21:23:27 +01:00
# include "editor/plugins/skeleton_2d_editor_plugin.h"
2017-10-03 18:49:32 +02:00
# include "editor/plugins/skeleton_editor_plugin.h"
2017-10-03 18:49:32 +02:00
# include "editor/plugins/skeleton_ik_editor_plugin.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/spatial_editor_plugin.h"
2018-02-21 13:38:21 +01:00
# include "editor/plugins/sprite_editor_plugin.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/sprite_frames_editor_plugin.h"
# include "editor/plugins/style_box_editor_plugin.h"
2018-05-28 17:52:28 +02:00
# include "editor/plugins/text_editor.h"
2017-08-26 17:46:49 +02:00
# include "editor/plugins/texture_editor_plugin.h"
# include "editor/plugins/texture_region_editor_plugin.h"
# include "editor/plugins/theme_editor_plugin.h"
# include "editor/plugins/tile_map_editor_plugin.h"
# include "editor/plugins/tile_set_editor_plugin.h"
2019-09-03 16:42:08 +02:00
# include "editor/plugins/version_control_editor_plugin.h"
2021-03-21 22:33:17 +01:00
# include "editor/plugins/viewport_preview_editor_plugin.h"
2018-07-14 23:15:42 +02:00
# include "editor/plugins/visual_shader_editor_plugin.h"
2019-12-24 08:17:23 +01:00
# include "editor/progress_dialog.h"
# include "editor/project_export.h"
# include "editor/project_settings_editor.h"
2017-08-26 17:46:49 +02:00
# include "editor/register_exporters.h"
2019-12-24 08:17:23 +01:00
# include "editor/run_settings_dialog.h"
2017-08-26 17:46:49 +02:00
# include "editor/script_editor_debugger.h"
2019-12-24 08:17:23 +01:00
# include "editor/settings_config_dialog.h"
2017-08-26 17:46:49 +02:00
2017-03-05 16:44:50 +01:00
# include <stdio.h>
2019-12-29 16:11:58 +01:00
# include <stdlib.h>
2014-02-18 05:21:06 +01:00
2021-05-04 16:00:45 +02:00
EditorNode * EditorNode : : singleton = nullptr ;
2014-02-10 02:10:30 +01:00
2019-12-24 01:20:54 +01:00
// The metadata key used to store and retrieve the version text to copy to the clipboard.
static const String META_TEXT_TO_COPY = " text_to_copy " ;
2020-05-27 06:49:05 +02:00
void EditorNode : : disambiguate_filenames ( const Vector < String > p_full_paths , Vector < String > & r_filenames ) {
// Keep track of a list of "index sets," i.e. sets of indices
// within disambiguated_scene_names which contain the same name.
2021-05-04 14:20:36 +02:00
Vector < Set < int > > index_sets ;
2020-05-27 06:49:05 +02:00
Map < String , int > scene_name_to_set_index ;
for ( int i = 0 ; i < r_filenames . size ( ) ; i + + ) {
String scene_name = r_filenames [ i ] ;
if ( ! scene_name_to_set_index . has ( scene_name ) ) {
index_sets . push_back ( Set < int > ( ) ) ;
scene_name_to_set_index . insert ( r_filenames [ i ] , index_sets . size ( ) - 1 ) ;
}
index_sets . write [ scene_name_to_set_index [ scene_name ] ] . insert ( i ) ;
}
// For each index set with a size > 1, we need to disambiguate
for ( int i = 0 ; i < index_sets . size ( ) ; i + + ) {
Set < int > iset = index_sets [ i ] ;
while ( iset . size ( ) > 1 ) {
// Append the parent folder to each scene name
for ( Set < int > : : Element * E = iset . front ( ) ; E ; E = E - > next ( ) ) {
int set_idx = E - > get ( ) ;
String scene_name = r_filenames [ set_idx ] ;
String full_path = p_full_paths [ set_idx ] ;
// Get rid of file extensions and res:// prefixes
if ( scene_name . rfind ( " . " ) > = 0 ) {
scene_name = scene_name . substr ( 0 , scene_name . rfind ( " . " ) ) ;
}
if ( full_path . begins_with ( " res:// " ) ) {
full_path = full_path . substr ( 6 ) ;
}
if ( full_path . rfind ( " . " ) > = 0 ) {
full_path = full_path . substr ( 0 , full_path . rfind ( " . " ) ) ;
}
int scene_name_size = scene_name . size ( ) ;
int full_path_size = full_path . size ( ) ;
int difference = full_path_size - scene_name_size ;
// Find just the parent folder of the current path and append it.
// If the current name is foo.tscn, and the full path is /some/folder/foo.tscn
// then slash_idx is the second '/', so that we select just "folder", and
// append that to yield "folder/foo.tscn".
if ( difference > 0 ) {
String parent = full_path . substr ( 0 , difference ) ;
int slash_idx = parent . rfind ( " / " ) ;
slash_idx = parent . rfind ( " / " , slash_idx - 1 ) ;
parent = slash_idx > = 0 ? parent . substr ( slash_idx + 1 ) : parent ;
r_filenames . write [ set_idx ] = parent + r_filenames [ set_idx ] ;
}
}
// Loop back through scene names and remove non-ambiguous names
bool can_proceed = false ;
Set < int > : : Element * E = iset . front ( ) ;
while ( E ) {
String scene_name = r_filenames [ E - > get ( ) ] ;
bool duplicate_found = false ;
for ( Set < int > : : Element * F = iset . front ( ) ; F ; F = F - > next ( ) ) {
if ( E - > get ( ) = = F - > get ( ) ) {
continue ;
}
String other_scene_name = r_filenames [ F - > get ( ) ] ;
if ( other_scene_name = = scene_name ) {
duplicate_found = true ;
break ;
}
}
Set < int > : : Element * to_erase = duplicate_found ? nullptr : E ;
// We need to check that we could actually append anymore names
// if we wanted to for disambiguation. If we can't, then we have
// to abort even with ambiguous names. We clean the full path
// and the scene name first to remove extensions so that this
// comparison actually works.
String path = p_full_paths [ E - > get ( ) ] ;
if ( path . begins_with ( " res:// " ) ) {
path = path . substr ( 6 ) ;
}
if ( path . rfind ( " . " ) > = 0 ) {
path = path . substr ( 0 , path . rfind ( " . " ) ) ;
}
if ( scene_name . rfind ( " . " ) > = 0 ) {
scene_name = scene_name . substr ( 0 , scene_name . rfind ( " . " ) ) ;
}
// We can proceed iff the full path is longer than the scene name,
// meaning that there is at least one more parent folder we can
// tack onto the name.
can_proceed = can_proceed | | ( path . size ( ) - scene_name . size ( ) ) > = 1 ;
E = E - > next ( ) ;
if ( to_erase ) {
iset . erase ( to_erase ) ;
}
}
if ( ! can_proceed ) {
break ;
}
}
}
}
2015-06-22 05:03:19 +02:00
void EditorNode : : _update_scene_tabs ( ) {
2017-12-20 19:41:02 +01:00
bool show_rb = EditorSettings : : get_singleton ( ) - > get ( " interface/scene_tabs/show_script_button " ) ;
2015-11-18 08:47:41 +01:00
2019-02-06 14:57:06 +01:00
OS : : get_singleton ( ) - > global_menu_clear ( " _dock " ) ;
2020-05-27 06:49:05 +02:00
// Get all scene names, which may be ambiguous
Vector < String > disambiguated_scene_names ;
Vector < String > full_path_names ;
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
disambiguated_scene_names . push_back ( editor_data . get_scene_title ( i ) ) ;
full_path_names . push_back ( editor_data . get_scene_path ( i ) ) ;
}
disambiguate_filenames ( full_path_names , disambiguated_scene_names ) ;
2015-06-22 05:03:19 +02:00
scene_tabs - > clear_tabs ( ) ;
2017-03-05 16:44:50 +01:00
Ref < Texture > script_icon = gui_base - > get_icon ( " Script " , " EditorIcons " ) ;
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
2019-03-11 22:54:23 +01:00
Node * type_node = editor_data . get_edited_scene_root ( i ) ;
2015-07-24 19:18:02 +02:00
Ref < Texture > icon ;
2019-03-11 22:54:23 +01:00
if ( type_node ) {
icon = EditorNode : : get_singleton ( ) - > get_object_icon ( type_node , " Node " ) ;
2015-07-24 19:18:02 +02:00
}
2015-06-22 05:03:19 +02:00
int current = editor_data . get_edited_scene ( ) ;
2017-03-05 16:44:50 +01:00
bool unsaved = ( i = = current ) ? saved_version ! = editor_data . get_undo_redo ( ) . get_version ( ) : editor_data . get_scene_version ( i ) ! = 0 ;
2020-05-27 06:49:05 +02:00
scene_tabs - > add_tab ( disambiguated_scene_names [ i ] + ( unsaved ? " (*) " : " " ) , icon ) ;
2015-07-24 19:18:02 +02:00
2019-02-06 14:57:06 +01:00
OS : : get_singleton ( ) - > global_menu_add_item ( " _dock " , editor_data . get_scene_title ( i ) + ( unsaved ? " (*) " : " " ) , GLOBAL_SCENE , i ) ;
2015-11-18 08:47:41 +01:00
if ( show_rb & & editor_data . get_scene_root_script ( i ) . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
scene_tabs - > set_tab_right_button ( i , script_icon ) ;
2015-07-26 15:44:10 +02:00
}
2015-06-22 05:03:19 +02:00
}
2019-02-06 14:57:06 +01:00
OS : : get_singleton ( ) - > global_menu_add_separator ( " _dock " ) ;
OS : : get_singleton ( ) - > global_menu_add_item ( " _dock " , TTR ( " New Window " ) , GLOBAL_NEW_WINDOW , Variant ( ) ) ;
2015-06-22 05:03:19 +02:00
scene_tabs - > set_current_tab ( editor_data . get_edited_scene ( ) ) ;
2017-11-16 23:57:57 +01:00
if ( scene_tabs - > get_offset_buttons_visible ( ) ) {
// move add button to fixed position on the tabbar
if ( scene_tab_add - > get_parent ( ) = = scene_tabs ) {
scene_tab_add - > set_position ( Point2 ( 0 , 0 ) ) ;
scene_tabs - > remove_child ( scene_tab_add ) ;
tabbar_container - > add_child ( scene_tab_add ) ;
tabbar_container - > move_child ( scene_tab_add , 1 ) ;
}
} else {
// move add button to after last tab
if ( scene_tab_add - > get_parent ( ) = = tabbar_container ) {
tabbar_container - > remove_child ( scene_tab_add ) ;
scene_tabs - > add_child ( scene_tab_add ) ;
}
2017-11-20 15:49:07 +01:00
Rect2 last_tab = Rect2 ( ) ;
2021-05-05 12:44:11 +02:00
if ( scene_tabs - > get_tab_count ( ) ! = 0 ) {
2017-11-20 15:49:07 +01:00
last_tab = scene_tabs - > get_tab_rect ( scene_tabs - > get_tab_count ( ) - 1 ) ;
2021-05-05 12:44:11 +02:00
}
2017-11-16 23:57:57 +01:00
scene_tab_add - > set_position ( Point2 ( last_tab . get_position ( ) . x + last_tab . get_size ( ) . x + 3 , last_tab . get_position ( ) . y ) ) ;
}
2015-06-22 05:03:19 +02:00
}
2019-09-03 16:42:08 +02:00
void EditorNode : : _version_control_menu_option ( int p_idx ) {
switch ( vcs_actions_menu - > get_item_id ( p_idx ) ) {
case RUN_VCS_SETTINGS : {
VersionControlEditorPlugin : : get_singleton ( ) - > popup_vcs_set_up_dialog ( gui_base ) ;
} break ;
case RUN_VCS_SHUT_DOWN : {
VersionControlEditorPlugin : : get_singleton ( ) - > shut_down ( ) ;
} break ;
}
}
2014-02-10 02:10:30 +01:00
void EditorNode : : _update_title ( ) {
2021-08-22 08:59:42 +02:00
const String appname = ProjectSettings : : get_singleton ( ) - > get ( " application/config/name " ) ;
2022-04-11 06:50:10 +02:00
String title = ( appname . empty ( ) ? TTR ( " Unnamed Project " ) : appname ) + String ( " - " ) + VERSION_NAME ;
2021-08-22 08:59:42 +02:00
const String edited = editor_data . get_edited_scene_root ( ) ? editor_data . get_edited_scene_root ( ) - > get_filename ( ) : String ( ) ;
2021-05-05 12:44:11 +02:00
if ( ! edited . empty ( ) ) {
2021-08-22 08:59:42 +02:00
// Display the edited scene name before the program name so that it can be seen in the OS task bar.
title = vformat ( " %s - %s " , edited . get_file ( ) , title ) ;
2021-05-05 12:44:11 +02:00
}
if ( unsaved_cache ) {
2021-08-22 08:59:42 +02:00
// Display the "modified" mark before anything else so that it can always be seen in the OS task bar.
title = vformat ( " (*) %s " , title ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
OS : : get_singleton ( ) - > set_window_title ( title ) ;
}
2017-05-20 17:38:03 +02:00
void EditorNode : : _unhandled_input ( const Ref < InputEvent > & p_event ) {
2021-05-05 12:44:11 +02:00
if ( Node : : get_viewport ( ) - > get_modal_stack_top ( ) ) {
2016-06-28 01:14:59 +02:00
return ; //ignore because of modal window
2021-05-05 12:44:11 +02:00
}
2016-06-28 01:14:59 +02:00
2017-05-20 17:38:03 +02:00
Ref < InputEventKey > k = p_event ;
if ( k . is_valid ( ) & & k - > is_pressed ( ) & & ! k - > is_echo ( ) & & ! gui_base - > get_viewport ( ) - > gui_has_modal_stack ( ) ) {
2018-03-13 21:20:59 +01:00
EditorPlugin * old_editor = editor_plugin_screen ;
2016-06-25 06:42:09 +02:00
if ( ED_IS_SHORTCUT ( " editor/next_tab " , p_event ) ) {
int next_tab = editor_data . get_edited_scene ( ) + 1 ;
next_tab % = editor_data . get_edited_scene_count ( ) ;
_scene_tab_changed ( next_tab ) ;
}
if ( ED_IS_SHORTCUT ( " editor/prev_tab " , p_event ) ) {
int next_tab = editor_data . get_edited_scene ( ) - 1 ;
next_tab = next_tab > = 0 ? next_tab : editor_data . get_edited_scene_count ( ) - 1 ;
_scene_tab_changed ( next_tab ) ;
}
2017-01-21 13:07:29 +01:00
if ( ED_IS_SHORTCUT ( " editor/filter_files " , p_event ) ) {
filesystem_dock - > focus_on_filter ( ) ;
}
2016-06-15 18:25:17 +02:00
2017-05-16 21:26:32 +02:00
if ( ED_IS_SHORTCUT ( " editor/editor_2d " , p_event ) ) {
_editor_select ( EDITOR_2D ) ;
} else if ( ED_IS_SHORTCUT ( " editor/editor_3d " , p_event ) ) {
_editor_select ( EDITOR_3D ) ;
} else if ( ED_IS_SHORTCUT ( " editor/editor_script " , p_event ) ) {
_editor_select ( EDITOR_SCRIPT ) ;
} else if ( ED_IS_SHORTCUT ( " editor/editor_help " , p_event ) ) {
emit_signal ( " request_help_search " , " " ) ;
2022-06-29 19:27:27 +02:00
} else if ( ED_IS_SHORTCUT ( " editor/editor_assetlib " , p_event ) & & AssetLibraryEditorPlugin : : is_available ( ) ) {
2017-05-16 21:26:32 +02:00
_editor_select ( EDITOR_ASSETLIB ) ;
} else if ( ED_IS_SHORTCUT ( " editor/editor_next " , p_event ) ) {
_editor_select_next ( ) ;
} else if ( ED_IS_SHORTCUT ( " editor/editor_prev " , p_event ) ) {
_editor_select_prev ( ) ;
2014-02-10 02:10:30 +01:00
}
2018-01-19 09:04:55 +01:00
2018-03-13 21:20:59 +01:00
if ( old_editor ! = editor_plugin_screen ) {
get_tree ( ) - > set_input_as_handled ( ) ;
}
2014-02-10 02:10:30 +01:00
}
}
void EditorNode : : _notification ( int p_what ) {
2019-07-14 12:26:22 +02:00
switch ( p_what ) {
case NOTIFICATION_PROCESS : {
2021-05-05 12:44:11 +02:00
if ( opening_prev & & ! confirmation - > is_visible ( ) ) {
2019-07-14 12:26:22 +02:00
opening_prev = false ;
2021-05-05 12:44:11 +02:00
}
2015-04-21 00:38:02 +02:00
2019-07-14 12:26:22 +02:00
if ( unsaved_cache ! = ( saved_version ! = editor_data . get_undo_redo ( ) . get_version ( ) ) ) {
unsaved_cache = ( saved_version ! = editor_data . get_undo_redo ( ) . get_version ( ) ) ;
_update_title ( ) ;
}
2014-02-10 02:10:30 +01:00
2019-07-14 12:26:22 +02:00
if ( last_checked_version ! = editor_data . get_undo_redo ( ) . get_version ( ) ) {
_update_scene_tabs ( ) ;
last_checked_version = editor_data . get_undo_redo ( ) . get_version ( ) ;
}
2014-02-10 02:10:30 +01:00
2021-10-26 08:44:50 +02:00
// Update the animation frame of the update spinner.
2019-07-14 12:26:22 +02:00
uint64_t frame = Engine : : get_singleton ( ) - > get_frames_drawn ( ) ;
2021-10-26 08:44:50 +02:00
uint64_t tick = OS : : get_singleton ( ) - > get_ticks_msec ( ) ;
2014-02-10 02:10:30 +01:00
2019-07-14 12:26:22 +02:00
if ( frame ! = update_spinner_step_frame & & ( tick - update_spinner_step_msec ) > ( 1000 / 8 ) ) {
update_spinner_step + + ;
2021-05-05 12:44:11 +02:00
if ( update_spinner_step > = 8 ) {
2019-07-14 12:26:22 +02:00
update_spinner_step = 0 ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2019-07-14 12:26:22 +02:00
update_spinner_step_msec = tick ;
update_spinner_step_frame = frame + 1 ;
2014-02-10 02:10:30 +01:00
2021-10-26 08:44:50 +02:00
// Update the icon itself only when the spinner is visible.
2019-07-14 12:26:22 +02:00
if ( EditorSettings : : get_singleton ( ) - > get ( " interface/editor/show_update_spinner " ) ) {
update_spinner - > set_icon ( gui_base - > get_icon ( " Progress " + itos ( update_spinner_step + 1 ) , " EditorIcons " ) ) ;
}
}
2014-02-10 02:10:30 +01:00
2019-07-14 12:26:22 +02:00
editor_selection - > update ( ) ;
2014-02-10 02:10:30 +01:00
2019-07-14 12:26:22 +02:00
scene_root - > set_size_override ( true , Size2 ( ProjectSettings : : get_singleton ( ) - > get ( " display/window/size/width " ) , ProjectSettings : : get_singleton ( ) - > get ( " display/window/size/height " ) ) ) ;
2018-12-11 16:52:25 +01:00
2019-07-14 12:26:22 +02:00
ResourceImporterTexture : : get_singleton ( ) - > update_imports ( ) ;
} break ;
2014-02-10 02:10:30 +01:00
2019-07-14 12:26:22 +02:00
case NOTIFICATION_ENTER_TREE : {
Engine : : get_singleton ( ) - > set_editor_hint ( true ) ;
2017-06-12 21:18:17 +02:00
2019-07-14 12:26:22 +02:00
OS : : get_singleton ( ) - > set_low_processor_usage_mode_sleep_usec ( int ( EDITOR_GET ( " interface/editor/low_processor_mode_sleep_usec " ) ) ) ;
get_tree ( ) - > get_root ( ) - > set_usage ( Viewport : : USAGE_2D_NO_SAMPLING ) ; //reduce memory usage
get_tree ( ) - > get_root ( ) - > set_disable_3d ( true ) ;
get_tree ( ) - > get_root ( ) - > set_as_audio_listener ( false ) ;
get_tree ( ) - > get_root ( ) - > set_as_audio_listener_2d ( false ) ;
get_tree ( ) - > set_auto_accept_quit ( false ) ;
2021-06-25 15:45:16 +02:00
# ifdef ANDROID_ENABLED
get_tree ( ) - > set_quit_on_go_back ( false ) ;
# endif
2019-07-14 12:26:22 +02:00
get_tree ( ) - > connect ( " files_dropped " , this , " _dropped_files " ) ;
2019-02-06 14:57:06 +01:00
get_tree ( ) - > connect ( " global_menu_action " , this , " _global_menu_action " ) ;
2014-02-10 02:10:30 +01:00
2019-07-14 12:26:22 +02:00
/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
} break ;
2017-08-13 16:21:45 +02:00
2019-07-14 12:26:22 +02:00
case NOTIFICATION_EXIT_TREE : {
editor_data . save_editor_external_data ( ) ;
2021-05-04 16:00:45 +02:00
FileAccess : : set_file_close_fail_notify_callback ( nullptr ) ;
2019-07-14 12:26:22 +02:00
log - > deinit ( ) ; // do not get messages anymore
editor_data . clear_edited_scenes ( ) ;
} break ;
2019-02-27 15:00:11 +01:00
2019-07-14 12:26:22 +02:00
case NOTIFICATION_READY : {
2021-09-27 18:27:01 +02:00
{
_initializing_addons = true ;
Vector < String > addons ;
if ( ProjectSettings : : get_singleton ( ) - > has_setting ( " editor_plugins/enabled " ) ) {
addons = ProjectSettings : : get_singleton ( ) - > get ( " editor_plugins/enabled " ) ;
}
for ( int i = 0 ; i < addons . size ( ) ; i + + ) {
set_addon_plugin_enabled ( addons [ i ] , true ) ;
}
_initializing_addons = false ;
}
2019-07-14 12:26:22 +02:00
VisualServer : : get_singleton ( ) - > viewport_set_hide_scenario ( get_scene_root ( ) - > get_viewport_rid ( ) , true ) ;
VisualServer : : get_singleton ( ) - > viewport_set_hide_canvas ( get_scene_root ( ) - > get_viewport_rid ( ) , true ) ;
VisualServer : : get_singleton ( ) - > viewport_set_disable_environment ( get_viewport ( ) - > get_viewport_rid ( ) , true ) ;
2015-06-22 05:03:19 +02:00
2019-07-14 12:26:22 +02:00
feature_profile_manager - > notify_changed ( ) ;
2014-02-10 02:10:30 +01:00
2019-07-14 12:26:22 +02:00
if ( ! main_editor_buttons [ EDITOR_3D ] - > is_visible ( ) ) { //may be hidden due to feature profile
_editor_select ( EDITOR_2D ) ;
} else {
_editor_select ( EDITOR_3D ) ;
}
2015-03-16 04:47:37 +01:00
2019-07-14 12:26:22 +02:00
_update_debug_options ( ) ;
2019-04-09 00:18:03 +02:00
2021-07-23 12:44:35 +02:00
// Save the project after opening to mark it as last modified, except in headless mode.
if ( OS : : get_singleton ( ) - > can_draw ( ) & & ! OS : : get_singleton ( ) - > is_no_window_mode_enabled ( ) ) {
ProjectSettings : : get_singleton ( ) - > save ( ) ;
}
2021-03-26 14:10:41 +01:00
2019-07-14 12:26:22 +02:00
/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
} break ;
2019-04-09 00:18:03 +02:00
2019-07-14 12:26:22 +02:00
case MainLoop : : NOTIFICATION_WM_FOCUS_IN : {
2021-04-11 15:39:31 +02:00
// Restore the original FPS cap after focusing back on the editor.
2019-07-14 12:26:22 +02:00
OS : : get_singleton ( ) - > set_low_processor_usage_mode_sleep_usec ( int ( EDITOR_GET ( " interface/editor/low_processor_mode_sleep_usec " ) ) ) ;
2014-02-10 02:10:30 +01:00
2019-07-14 12:26:22 +02:00
EditorFileSystem : : get_singleton ( ) - > scan_changes ( ) ;
2021-02-11 01:08:49 +01:00
_scan_external_changes ( ) ;
2019-07-14 12:26:22 +02:00
} break ;
2014-02-10 02:10:30 +01:00
2019-07-14 12:26:22 +02:00
case MainLoop : : NOTIFICATION_WM_FOCUS_OUT : {
2021-04-11 15:39:31 +02:00
// Save on focus loss before applying the FPS limit to avoid slowing down the saving process.
if ( EDITOR_GET ( " interface/editor/save_on_focus_loss " ) ) {
_menu_option_confirm ( FILE_SAVE_SCENE , false ) ;
}
// Set a low FPS cap to decrease CPU/GPU usage while the editor is unfocused.
2019-07-14 12:26:22 +02:00
OS : : get_singleton ( ) - > set_low_processor_usage_mode_sleep_usec ( int ( EDITOR_GET ( " interface/editor/unfocused_low_processor_mode_sleep_usec " ) ) ) ;
} break ;
2014-02-10 02:10:30 +01:00
2019-08-05 19:46:23 +02:00
case MainLoop : : NOTIFICATION_WM_ABOUT : {
show_about ( ) ;
} break ;
2019-07-14 12:26:22 +02:00
case MainLoop : : NOTIFICATION_WM_QUIT_REQUEST : {
_menu_option_confirm ( FILE_QUIT , false ) ;
} break ;
2019-05-29 23:12:19 +02:00
2019-07-14 12:26:22 +02:00
case EditorSettings : : NOTIFICATION_EDITOR_SETTINGS_CHANGED : {
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 ) ) ;
2021-05-12 15:08:21 +02:00
theme = create_custom_theme ( theme_base - > get_theme ( ) ) ;
2014-02-10 02:10:30 +01:00
2019-07-14 12:26:22 +02:00
theme_base - > set_theme ( theme ) ;
gui_base - > set_theme ( theme ) ;
2014-02-10 02:10:30 +01:00
2019-07-14 12:26:22 +02:00
gui_base - > add_style_override ( " panel " , gui_base - > get_stylebox ( " Background " , " EditorStyles " ) ) ;
scene_root_parent - > add_style_override ( " panel " , gui_base - > get_stylebox ( " Content " , " EditorStyles " ) ) ;
bottom_panel - > add_style_override ( " panel " , gui_base - > get_stylebox ( " panel " , " TabContainer " ) ) ;
scene_tabs - > add_style_override ( " tab_fg " , gui_base - > get_stylebox ( " SceneTabFG " , " EditorStyles " ) ) ;
scene_tabs - > add_style_override ( " tab_bg " , gui_base - > get_stylebox ( " SceneTabBG " , " EditorStyles " ) ) ;
2017-08-30 01:03:13 +02:00
2019-07-14 12:26:22 +02:00
file_menu - > add_style_override ( " hover " , gui_base - > get_stylebox ( " MenuHover " , " EditorStyles " ) ) ;
project_menu - > add_style_override ( " hover " , gui_base - > get_stylebox ( " MenuHover " , " EditorStyles " ) ) ;
debug_menu - > add_style_override ( " hover " , gui_base - > get_stylebox ( " MenuHover " , " EditorStyles " ) ) ;
settings_menu - > add_style_override ( " hover " , gui_base - > get_stylebox ( " MenuHover " , " EditorStyles " ) ) ;
help_menu - > add_style_override ( " hover " , gui_base - > get_stylebox ( " MenuHover " , " EditorStyles " ) ) ;
2017-10-20 12:24:00 +02:00
2019-07-14 12:26:22 +02:00
if ( EDITOR_GET ( " interface/scene_tabs/resize_if_many_tabs " ) ) {
scene_tabs - > set_min_width ( int ( EDITOR_GET ( " interface/scene_tabs/minimum_width " ) ) * EDSCALE ) ;
} else {
scene_tabs - > set_min_width ( 0 ) ;
}
_update_scene_tabs ( ) ;
recent_scenes - > set_as_minsize ( ) ;
// debugger area
2021-05-05 12:44:11 +02:00
if ( ScriptEditor : : get_singleton ( ) - > get_debugger ( ) - > is_visible ( ) ) {
2019-07-14 12:26:22 +02:00
bottom_panel - > add_style_override ( " panel " , gui_base - > get_stylebox ( " BottomPanelDebuggerOverride " , " EditorStyles " ) ) ;
2021-05-05 12:44:11 +02:00
}
2017-09-18 21:06:55 +02:00
2019-07-14 12:26:22 +02:00
// update_icons
for ( int i = 0 ; i < singleton - > main_editor_buttons . size ( ) ; i + + ) {
ToolButton * tb = singleton - > main_editor_buttons [ i ] ;
EditorPlugin * p_editor = singleton - > editor_table [ i ] ;
Ref < Texture > icon = p_editor - > get_icon ( ) ;
2017-12-06 23:27:45 +01:00
2019-07-14 12:26:22 +02:00
if ( icon . is_valid ( ) ) {
tb - > set_icon ( icon ) ;
} else if ( singleton - > gui_base - > has_icon ( p_editor - > get_name ( ) , " EditorIcons " ) ) {
tb - > set_icon ( singleton - > gui_base - > get_icon ( p_editor - > get_name ( ) , " EditorIcons " ) ) ;
}
2017-12-06 23:27:45 +01:00
}
2018-02-25 17:04:16 +01:00
2019-07-14 12:26:22 +02:00
_build_icon_type_cache ( ) ;
2018-02-25 17:04:16 +01:00
2019-07-14 12:26:22 +02:00
play_button - > set_icon ( gui_base - > get_icon ( " MainPlay " , " EditorIcons " ) ) ;
play_scene_button - > set_icon ( gui_base - > get_icon ( " PlayScene " , " EditorIcons " ) ) ;
play_custom_scene_button - > set_icon ( gui_base - > get_icon ( " PlayCustom " , " EditorIcons " ) ) ;
pause_button - > set_icon ( gui_base - > get_icon ( " Pause " , " EditorIcons " ) ) ;
stop_button - > set_icon ( gui_base - > get_icon ( " Stop " , " EditorIcons " ) ) ;
2017-08-30 01:03:13 +02:00
2019-07-14 12:26:22 +02:00
prev_scene - > set_icon ( gui_base - > get_icon ( " PrevScene " , " EditorIcons " ) ) ;
distraction_free - > set_icon ( gui_base - > get_icon ( " DistractionFree " , " EditorIcons " ) ) ;
scene_tab_add - > set_icon ( gui_base - > get_icon ( " Add " , " EditorIcons " ) ) ;
2017-08-30 01:03:13 +02:00
2019-07-29 23:08:05 +02:00
bottom_panel_raise - > set_icon ( gui_base - > get_icon ( " ExpandBottomDock " , " EditorIcons " ) ) ;
2019-07-14 12:26:22 +02:00
// clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons")); don't have access to that node. needs to become a class property
dock_tab_move_left - > set_icon ( theme - > get_icon ( " Back " , " EditorIcons " ) ) ;
dock_tab_move_right - > set_icon ( theme - > get_icon ( " Forward " , " EditorIcons " ) ) ;
2018-02-25 17:04:16 +01:00
2019-07-14 12:26:22 +02:00
PopupMenu * p = help_menu - > get_popup ( ) ;
p - > set_item_icon ( p - > get_item_index ( HELP_SEARCH ) , gui_base - > get_icon ( " HelpSearch " , " EditorIcons " ) ) ;
2022-04-24 17:21:14 +02:00
p - > set_item_icon ( p - > get_item_index ( HELP_DOCS ) , gui_base - > get_icon ( " ExternalLink " , " EditorIcons " ) ) ;
p - > set_item_icon ( p - > get_item_index ( HELP_QA ) , gui_base - > get_icon ( " ExternalLink " , " EditorIcons " ) ) ;
p - > set_item_icon ( p - > get_item_index ( HELP_REPORT_A_BUG ) , gui_base - > get_icon ( " ExternalLink " , " EditorIcons " ) ) ;
p - > set_item_icon ( p - > get_item_index ( HELP_SUGGEST_A_FEATURE ) , gui_base - > get_icon ( " ExternalLink " , " EditorIcons " ) ) ;
p - > set_item_icon ( p - > get_item_index ( HELP_SEND_DOCS_FEEDBACK ) , gui_base - > get_icon ( " ExternalLink " , " EditorIcons " ) ) ;
p - > set_item_icon ( p - > get_item_index ( HELP_COMMUNITY ) , gui_base - > get_icon ( " ExternalLink " , " EditorIcons " ) ) ;
2019-07-14 12:26:22 +02:00
p - > set_item_icon ( p - > get_item_index ( HELP_ABOUT ) , gui_base - > get_icon ( " Godot " , " EditorIcons " ) ) ;
2021-05-15 01:57:21 +02:00
p - > set_item_icon ( p - > get_item_index ( HELP_SUPPORT_GODOT_DEVELOPMENT ) , gui_base - > get_icon ( " Heart " , " EditorIcons " ) ) ;
2019-07-14 12:26:22 +02:00
_update_update_spinner ( ) ;
} break ;
2017-11-21 08:46:39 +01:00
2019-07-14 12:26:22 +02:00
case Control : : NOTIFICATION_RESIZED : {
_update_scene_tabs ( ) ;
} break ;
2017-11-16 23:57:57 +01:00
}
2014-02-10 02:10:30 +01:00
}
2018-12-11 16:52:25 +01:00
void EditorNode : : _update_update_spinner ( ) {
update_spinner - > set_visible ( EditorSettings : : get_singleton ( ) - > get ( " interface/editor/show_update_spinner " ) ) ;
2021-08-03 17:22:46 +02:00
const bool update_continuously = EditorSettings : : get_singleton ( ) - > get ( " interface/editor/update_continuously " ) ;
2021-10-05 20:05:57 +02:00
const bool vital_only = EditorSettings : : get_singleton ( ) - > get ( " interface/editor/update_vital_only " ) ;
2018-12-11 16:52:25 +01:00
PopupMenu * update_popup = update_spinner - > get_popup ( ) ;
update_popup - > set_item_checked ( update_popup - > get_item_index ( SETTINGS_UPDATE_CONTINUOUSLY ) , update_continuously ) ;
2021-10-05 20:05:57 +02:00
if ( update_continuously ) {
update_popup - > set_item_checked ( update_popup - > get_item_index ( SETTINGS_UPDATE_WHEN_CHANGED ) , false ) ;
update_popup - > set_item_checked ( update_popup - > get_item_index ( SETTINGS_UPDATE_VITAL_ONLY ) , false ) ;
} else {
update_popup - > set_item_checked ( update_popup - > get_item_index ( SETTINGS_UPDATE_WHEN_CHANGED ) , ! vital_only ) ;
update_popup - > set_item_checked ( update_popup - > get_item_index ( SETTINGS_UPDATE_VITAL_ONLY ) , vital_only ) ;
}
2018-12-11 16:52:25 +01:00
2021-08-03 17:22:46 +02:00
if ( update_continuously ) {
update_spinner - > set_tooltip ( TTR ( " Spins when the editor window redraws. \n Update Continuously is enabled, which can increase power usage. Click to disable it. " ) ) ;
// Use a different color for the update spinner when Update Continuously is enabled,
// as this feature should only be enabled for troubleshooting purposes.
// Make the icon modulate color overbright because icons are not completely white on a dark theme.
// On a light theme, icons are dark, so we need to modulate them with an even brighter color.
const bool dark_theme = EditorSettings : : get_singleton ( ) - > is_dark_theme ( ) ;
update_spinner - > set_self_modulate (
gui_base - > get_color ( " error_color " , " Editor " ) * ( dark_theme ? Color ( 1.1 , 1.1 , 1.1 ) : Color ( 4.25 , 4.25 , 4.25 ) ) ) ;
} else {
update_spinner - > set_tooltip ( TTR ( " Spins when the editor window redraws. " ) ) ;
update_spinner - > set_self_modulate ( Color ( 1 , 1 , 1 ) ) ;
}
2018-12-11 16:52:25 +01:00
OS : : get_singleton ( ) - > set_low_processor_usage_mode ( ! update_continuously ) ;
2021-10-05 20:05:57 +02:00
// Only set low priority redraws to false in the editor.
// When we run the project in the editor, we don't want it to prevent
// rendering any frames.
OS : : get_singleton ( ) - > set_update_vital_only ( vital_only & & ! update_continuously ) ;
2018-12-11 16:52:25 +01:00
}
2018-07-19 17:34:22 +02:00
void EditorNode : : _on_plugin_ready ( Object * p_script , const String & p_activate_name ) {
Ref < Script > script = Object : : cast_to < Script > ( p_script ) ;
2021-05-05 12:44:11 +02:00
if ( script . is_null ( ) ) {
2018-07-19 17:34:22 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2018-07-19 17:34:22 +02:00
if ( p_activate_name . length ( ) ) {
set_addon_plugin_enabled ( p_activate_name , true ) ;
}
project_settings - > update_plugins ( ) ;
project_settings - > hide ( ) ;
push_item ( script . operator - > ( ) ) ;
}
2021-05-09 14:17:15 +02:00
void EditorNode : : _remove_plugin_from_enabled ( const String & p_name ) {
ProjectSettings * ps = ProjectSettings : : get_singleton ( ) ;
PoolStringArray enabled_plugins = ps - > get ( " editor_plugins/enabled " ) ;
for ( int i = 0 ; i < enabled_plugins . size ( ) ; + + i ) {
if ( enabled_plugins . get ( i ) = = p_name ) {
enabled_plugins . remove ( i ) ;
break ;
}
}
ps - > set ( " editor_plugins/enabled " , enabled_plugins ) ;
}
2018-11-21 01:47:48 +01:00
void EditorNode : : _resources_changed ( const PoolVector < String > & p_resources ) {
2021-05-04 14:20:36 +02:00
List < Ref < Resource > > changed ;
2014-02-10 02:10:30 +01:00
2018-11-21 01:47:48 +01:00
int rc = p_resources . size ( ) ;
for ( int i = 0 ; i < rc ; i + + ) {
Ref < Resource > res ( ResourceCache : : get ( p_resources . get ( i ) ) ) ;
if ( res . is_null ( ) ) {
continue ;
}
2015-05-31 06:59:42 +02:00
2021-05-05 12:44:11 +02:00
if ( ! res - > editor_can_reload_from_file ( ) ) {
2018-11-21 01:47:48 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
if ( ! res - > get_path ( ) . is_resource_file ( ) & & ! res - > get_path ( ) . is_abs_path ( ) ) {
2018-11-21 01:47:48 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
if ( ! FileAccess : : exists ( res - > get_path ( ) ) ) {
2018-11-21 01:47:48 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2016-02-10 07:41:48 +01:00
2018-11-21 01:47:48 +01:00
if ( res - > get_import_path ( ) ! = String ( ) ) {
//this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback
continue ;
}
2014-02-10 02:10:30 +01:00
2018-11-21 01:47:48 +01:00
changed . push_back ( res ) ;
}
2016-05-27 19:18:40 +02:00
2018-11-21 01:47:48 +01:00
if ( changed . size ( ) ) {
2021-05-04 14:20:36 +02:00
for ( List < Ref < Resource > > : : Element * E = changed . front ( ) ; E ; E = E - > next ( ) ) {
2018-11-21 01:47:48 +01:00
E - > get ( ) - > reload_from_file ( ) ;
}
}
}
2016-05-27 19:18:40 +02:00
2018-11-21 01:47:48 +01:00
void EditorNode : : _fs_changed ( ) {
for ( Set < FileDialog * > : : Element * E = file_dialogs . front ( ) ; E ; E = E - > next ( ) ) {
E - > get ( ) - > invalidate ( ) ;
}
2016-05-27 19:18:40 +02:00
2018-11-21 01:47:48 +01:00
for ( Set < EditorFileDialog * > : : Element * E = editor_file_dialogs . front ( ) ; E ; E = E - > next ( ) ) {
E - > get ( ) - > invalidate ( ) ;
2016-05-27 19:18:40 +02:00
}
2017-06-29 19:37:54 +02:00
_mark_unsaved_scenes ( ) ;
2017-12-30 10:39:09 +01:00
2020-01-07 13:29:02 +01:00
// FIXME: Move this to a cleaner location, it's hacky to do this is _fs_changed.
String export_error ;
2022-07-10 22:39:16 +02:00
Error err = OK ;
2017-12-30 10:39:09 +01:00
if ( export_defer . preset ! = " " & & ! EditorFileSystem : : get_singleton ( ) - > is_scanning ( ) ) {
2020-01-07 13:29:02 +01:00
String preset_name = export_defer . preset ;
// Ensures export_project does not loop infinitely, because notifications may
// come during the export.
export_defer . preset = " " ;
2017-12-30 10:39:09 +01:00
Ref < EditorExportPreset > preset ;
for ( int i = 0 ; i < EditorExport : : get_singleton ( ) - > get_export_preset_count ( ) ; + + i ) {
preset = EditorExport : : get_singleton ( ) - > get_export_preset ( i ) ;
2020-01-07 13:29:02 +01:00
if ( preset - > get_name ( ) = = preset_name ) {
2017-12-30 10:39:09 +01:00
break ;
}
preset . unref ( ) ;
}
2021-04-06 01:44:15 +02:00
2017-12-30 10:39:09 +01:00
if ( preset . is_null ( ) ) {
2021-04-06 01:44:15 +02:00
DirAccessRef da = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
if ( da - > file_exists ( " res://export_presets.cfg " ) ) {
2022-07-10 22:39:16 +02:00
err = FAILED ;
2021-04-06 01:44:15 +02:00
export_error = vformat (
" Invalid export preset name: %s. \n The following presets were detected in this project's `export_presets.cfg`: \n \n " ,
preset_name ) ;
for ( int i = 0 ; i < EditorExport : : get_singleton ( ) - > get_export_preset_count ( ) ; + + i ) {
// Write the preset name between double quotes since it needs to be written between quotes on the command line if it contains spaces.
export_error + = vformat ( " \" %s \" \n " , EditorExport : : get_singleton ( ) - > get_export_preset ( i ) - > get_name ( ) ) ;
}
} else {
2022-07-10 22:39:16 +02:00
err = FAILED ;
2021-04-06 01:44:15 +02:00
export_error = " This project doesn't have an `export_presets.cfg` file at its root. \n Create an export preset from the \" Project > Export \" dialog and try again. " ;
}
2017-12-30 10:39:09 +01:00
} else {
Ref < EditorExportPlatform > platform = preset - > get_platform ( ) ;
2020-11-17 18:02:41 +01:00
const String export_path = export_defer . path . empty ( ) ? preset - > get_export_path ( ) : export_defer . path ;
if ( export_path . empty ( ) ) {
2022-07-10 22:39:16 +02:00
err = FAILED ;
2021-04-06 01:44:15 +02:00
export_error = vformat ( " Export preset \" %s \" doesn't have a default export path, and none was specified. " , preset_name ) ;
2020-11-17 18:02:41 +01:00
} else if ( platform . is_null ( ) ) {
2022-07-10 22:39:16 +02:00
err = FAILED ;
2021-04-06 01:44:15 +02:00
export_error = vformat ( " Export preset \" %s \" doesn't have a matching platform. " , preset_name ) ;
2017-12-30 10:39:09 +01:00
} else {
2020-01-08 14:22:50 +01:00
if ( export_defer . pack_only ) { // Only export .pck or .zip data pack.
2020-11-17 18:02:41 +01:00
if ( export_path . ends_with ( " .zip " ) ) {
err = platform - > export_zip ( preset , export_defer . debug , export_path ) ;
} else if ( export_path . ends_with ( " .pck " ) ) {
err = platform - > export_pack ( preset , export_defer . debug , export_path ) ;
2017-12-30 10:39:09 +01:00
}
2020-01-07 13:29:02 +01:00
} else { // Normal project export.
String config_error ;
bool missing_templates ;
if ( ! platform - > can_export ( preset , config_error , missing_templates ) ) {
2021-04-06 01:44:15 +02:00
ERR_PRINT ( vformat ( " Cannot export project with preset \" %s \" due to configuration errors: \n %s " , preset_name , config_error ) ) ;
2020-01-07 13:29:02 +01:00
err = missing_templates ? ERR_FILE_NOT_FOUND : ERR_UNCONFIGURED ;
} else {
2022-06-02 10:12:50 +02:00
platform - > clear_messages ( ) ;
2020-11-17 18:02:41 +01:00
err = platform - > export_project ( preset , export_defer . debug , export_path ) ;
2020-01-07 13:29:02 +01:00
}
2018-04-04 16:13:06 +02:00
}
2022-06-02 10:12:50 +02:00
if ( err ! = OK ) {
export_error = vformat ( " Project export for preset \" %s \" failed. " , preset_name ) ;
} else if ( platform - > get_worst_message_type ( ) > = EditorExportPlatform : : EXPORT_MESSAGE_WARNING ) {
2022-07-10 22:39:16 +02:00
export_error = vformat ( " Project export for preset \" %s \" completed with warnings. " , preset_name ) ;
2017-12-30 10:39:09 +01:00
}
}
}
2022-07-10 22:39:16 +02:00
if ( err ! = OK ) {
2020-01-07 13:29:02 +01:00
ERR_PRINT ( export_error ) ;
OS : : get_singleton ( ) - > set_exit_code ( EXIT_FAILURE ) ;
2022-07-10 22:39:16 +02:00
} else if ( ! export_error . empty ( ) ) {
WARN_PRINT ( export_error ) ;
2020-01-07 13:29:02 +01:00
}
2019-01-17 13:09:01 +01:00
_exit_editor ( ) ;
2017-12-30 10:39:09 +01:00
}
2017-02-01 13:45:45 +01:00
}
2016-05-27 19:18:40 +02:00
2017-08-31 23:57:03 +02:00
void EditorNode : : _resources_reimported ( const Vector < String > & p_resources ) {
List < String > scenes ; //will load later
2019-06-04 05:36:23 +02:00
int current_tab = scene_tabs - > get_current_tab ( ) ;
2017-08-31 23:57:03 +02:00
for ( int i = 0 ; i < p_resources . size ( ) ; i + + ) {
String file_type = ResourceLoader : : get_resource_type ( p_resources [ i ] ) ;
if ( file_type = = " PackedScene " ) {
scenes . push_back ( p_resources [ i ] ) ;
//reload later if needed, first go with normal resources
continue ;
}
if ( ! ResourceCache : : has ( p_resources [ i ] ) ) {
continue ; //not loaded, no need to reload
}
//reload normally
Resource * resource = ResourceCache : : get ( p_resources [ i ] ) ;
if ( resource ) {
resource - > reload_from_file ( ) ;
}
}
for ( List < String > : : Element * E = scenes . front ( ) ; E ; E = E - > next ( ) ) {
reload_scene ( E - > get ( ) ) ;
}
2019-06-04 05:36:23 +02:00
scene_tabs - > set_current_tab ( current_tab ) ;
2017-08-31 23:57:03 +02:00
}
2017-02-01 13:45:45 +01:00
void EditorNode : : _sources_changed ( bool p_exist ) {
if ( waiting_for_first_scan ) {
2019-02-27 22:14:24 +01:00
waiting_for_first_scan = false ;
2014-02-10 02:10:30 +01:00
2020-01-14 11:32:15 +01:00
// Start preview thread now that it's safe.
if ( ! singleton - > cmdline_export_mode ) {
EditorResourcePreview : : get_singleton ( ) - > start ( ) ;
}
2019-02-27 17:31:11 +01:00
2019-02-27 15:00:11 +01:00
_load_docks ( ) ;
2017-03-05 16:44:50 +01:00
if ( defer_load_scene ! = " " ) {
2023-01-22 19:42:34 +01:00
OS : : get_singleton ( ) - > benchmark_begin_measure ( " editor_load_scene " ) ;
2017-02-01 13:45:45 +01:00
load_scene ( defer_load_scene ) ;
2017-03-05 16:44:50 +01:00
defer_load_scene = " " ;
2023-01-22 19:42:34 +01:00
OS : : get_singleton ( ) - > benchmark_end_measure ( " editor_load_scene " ) ;
OS : : get_singleton ( ) - > benchmark_dump ( ) ;
2017-02-01 13:45:45 +01:00
}
2014-02-10 02:10:30 +01:00
}
}
2021-02-11 01:08:49 +01:00
void EditorNode : : _scan_external_changes ( ) {
disk_changed_list - > clear ( ) ;
TreeItem * r = disk_changed_list - > create_item ( ) ;
disk_changed_list - > set_hide_root ( true ) ;
bool need_reload = false ;
// Check if any edited scene has changed.
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
2021-02-26 23:18:50 +01:00
DirAccessRef da = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
if ( editor_data . get_scene_path ( i ) = = " " | | ! da - > file_exists ( editor_data . get_scene_path ( i ) ) ) {
2021-02-11 01:08:49 +01:00
continue ;
}
uint64_t last_date = editor_data . get_scene_modified_time ( i ) ;
uint64_t date = FileAccess : : get_modified_time ( editor_data . get_scene_path ( i ) ) ;
if ( date > last_date ) {
TreeItem * ti = disk_changed_list - > create_item ( r ) ;
ti - > set_text ( 0 , editor_data . get_scene_path ( i ) . get_file ( ) ) ;
need_reload = true ;
}
}
String project_settings_path = ProjectSettings : : get_singleton ( ) - > get_resource_path ( ) . plus_file ( " project.godot " ) ;
if ( FileAccess : : get_modified_time ( project_settings_path ) > ProjectSettings : : get_singleton ( ) - > get_last_saved_time ( ) ) {
TreeItem * ti = disk_changed_list - > create_item ( r ) ;
ti - > set_text ( 0 , " project.godot " ) ;
need_reload = true ;
}
if ( need_reload ) {
disk_changed - > call_deferred ( " popup_centered_ratio " , 0.5 ) ;
}
}
void EditorNode : : _resave_scenes ( String p_str ) {
save_all_scenes ( ) ;
ProjectSettings : : get_singleton ( ) - > save ( ) ;
disk_changed - > hide ( ) ;
}
void EditorNode : : _reload_modified_scenes ( ) {
int current_idx = editor_data . get_edited_scene ( ) ;
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
if ( editor_data . get_scene_path ( i ) = = " " ) {
continue ;
}
uint64_t last_date = editor_data . get_scene_modified_time ( i ) ;
uint64_t date = FileAccess : : get_modified_time ( editor_data . get_scene_path ( i ) ) ;
if ( date > last_date ) {
String filename = editor_data . get_scene_path ( i ) ;
editor_data . set_edited_scene ( i ) ;
_remove_edited_scene ( false ) ;
Error err = load_scene ( filename , false , false , true , false , true ) ;
if ( err ! = OK ) {
ERR_PRINT ( vformat ( " Failed to load scene: %s " , filename ) ) ;
}
editor_data . move_edited_scene_to_index ( i ) ;
}
}
get_undo_redo ( ) - > clear_history ( false ) ;
set_current_scene ( current_idx ) ;
_update_scene_tabs ( ) ;
disk_changed - > hide ( ) ;
}
void EditorNode : : _reload_project_settings ( ) {
ProjectSettings : : get_singleton ( ) - > setup ( ProjectSettings : : get_singleton ( ) - > get_resource_path ( ) , String ( ) , true ) ;
}
2014-02-10 02:10:30 +01:00
void EditorNode : : _vp_resized ( ) {
}
2019-12-24 01:20:54 +01:00
void EditorNode : : _version_button_pressed ( ) {
OS : : get_singleton ( ) - > set_clipboard ( version_btn - > get_meta ( META_TEXT_TO_COPY ) ) ;
}
2014-02-10 02:10:30 +01:00
void EditorNode : : _node_renamed ( ) {
2021-05-05 12:44:11 +02:00
if ( get_inspector ( ) ) {
2018-05-17 08:01:47 +02:00
get_inspector ( ) - > update_tree ( ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-05-16 21:26:32 +02:00
void EditorNode : : _editor_select_next ( ) {
int editor = _get_current_main_editor ( ) ;
2019-04-09 00:18:03 +02:00
do {
if ( editor = = editor_table . size ( ) - 1 ) {
editor = 0 ;
} else {
editor + + ;
}
2019-12-11 06:27:21 +01:00
} while ( ! main_editor_buttons [ editor ] - > is_visible ( ) ) ;
2019-04-09 00:18:03 +02:00
2017-05-16 21:26:32 +02:00
_editor_select ( editor ) ;
}
void EditorNode : : _editor_select_prev ( ) {
int editor = _get_current_main_editor ( ) ;
2019-04-09 00:18:03 +02:00
do {
if ( editor = = 0 ) {
editor = editor_table . size ( ) - 1 ;
} else {
editor - - ;
}
2019-12-11 06:27:21 +01:00
} while ( ! main_editor_buttons [ editor ] - > is_visible ( ) ) ;
2019-04-09 00:18:03 +02:00
2017-05-16 21:26:32 +02:00
_editor_select ( editor ) ;
}
2018-11-02 04:44:40 +01:00
Error EditorNode : : load_resource ( const String & p_resource , bool p_ignore_broken_deps ) {
dependency_errors . clear ( ) ;
Error err ;
RES res = ResourceLoader : : load ( p_resource , " " , false , & err ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! res . is_valid ( ) , ERR_CANT_OPEN ) ;
2014-02-10 02:10:30 +01:00
2018-11-02 04:44:40 +01:00
if ( ! p_ignore_broken_deps & & dependency_errors . has ( p_resource ) ) {
//current_option = -1;
Vector < String > errors ;
for ( Set < String > : : Element * E = dependency_errors [ p_resource ] . front ( ) ; E ; E = E - > next ( ) ) {
errors . push_back ( E - > get ( ) ) ;
}
dependency_error - > show ( DependencyErrorDialog : : MODE_RESOURCE , p_resource , errors ) ;
dependency_errors . erase ( p_resource ) ;
return ERR_FILE_MISSING_DEPENDENCIES ;
}
inspector_dock - > edit_resource ( res ) ;
2014-02-10 02:10:30 +01:00
return OK ;
}
void EditorNode : : edit_node ( Node * p_node ) {
push_item ( p_node ) ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : save_resource_in_path ( const Ref < Resource > & p_resource , const String & p_path ) {
2015-09-01 05:49:47 +02:00
editor_data . apply_changes_in_editors ( ) ;
2017-03-05 16:44:50 +01:00
int flg = 0 ;
2021-05-05 12:44:11 +02:00
if ( EditorSettings : : get_singleton ( ) - > get ( " filesystem/on_save/compress_binary_resources " ) ) {
2017-03-05 16:44:50 +01:00
flg | = ResourceSaver : : FLAG_COMPRESS ;
2021-05-05 12:44:11 +02:00
}
2015-09-01 05:49:47 +02:00
2017-07-19 22:00:46 +02:00
String path = ProjectSettings : : get_singleton ( ) - > localize_path ( p_path ) ;
2017-03-05 16:44:50 +01:00
Error err = ResourceSaver : : save ( path , p_resource , flg | ResourceSaver : : FLAG_REPLACE_SUBRESOURCE_PATHS ) ;
2015-09-01 05:49:47 +02:00
2017-03-05 16:44:50 +01:00
if ( err ! = OK ) {
2019-03-04 15:06:15 +01:00
if ( ResourceLoader : : is_imported ( p_resource - > get_path ( ) ) ) {
show_accept ( TTR ( " Imported resources can't be saved. " ) , TTR ( " OK " ) ) ;
} else {
show_accept ( TTR ( " Error saving resource! " ) , TTR ( " OK " ) ) ;
}
2017-03-05 16:44:50 +01:00
return ;
2015-09-01 05:49:47 +02:00
}
2017-03-05 16:44:50 +01:00
( ( Resource * ) p_resource . ptr ( ) ) - > set_path ( path ) ;
emit_signal ( " resource_saved " , p_resource ) ;
2018-01-12 22:43:29 +01:00
editor_data . notify_resource_saved ( p_resource ) ;
2015-09-01 05:49:47 +02:00
}
2017-03-05 16:44:50 +01:00
void EditorNode : : save_resource ( const Ref < Resource > & p_resource ) {
2015-09-01 05:49:47 +02:00
if ( p_resource - > get_path ( ) . is_resource_file ( ) ) {
2017-03-05 16:44:50 +01:00
save_resource_in_path ( p_resource , p_resource - > get_path ( ) ) ;
2015-09-01 05:49:47 +02:00
} else {
save_resource_as ( p_resource ) ;
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void EditorNode : : save_resource_as ( const Ref < Resource > & p_resource , const String & p_at_path ) {
2019-03-04 15:06:15 +01:00
{
String path = p_resource - > get_path ( ) ;
int srpos = path . find ( " :: " ) ;
if ( srpos ! = - 1 ) {
String base = path . substr ( 0 , srpos ) ;
if ( ! get_edited_scene ( ) | | get_edited_scene ( ) - > get_filename ( ) ! = base ) {
show_warning ( TTR ( " This resource can't be saved because it does not belong to the edited scene. Make it unique first. " ) ) ;
return ;
}
}
}
2015-09-01 05:49:47 +02:00
file - > set_mode ( EditorFileDialog : : MODE_SAVE_FILE ) ;
2018-11-18 15:17:04 +01:00
saving_resource = p_resource ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
current_option = RESOURCE_SAVE_AS ;
2015-09-01 05:49:47 +02:00
List < String > extensions ;
2017-03-05 16:44:50 +01:00
Ref < PackedScene > sd = memnew ( PackedScene ) ;
ResourceSaver : : get_recognized_extensions ( p_resource , & extensions ) ;
2015-09-01 05:49:47 +02:00
file - > clear_filters ( ) ;
2015-12-31 17:12:27 +01:00
List < String > preferred ;
2020-12-13 02:37:23 +01:00
for ( List < String > : : Element * E = extensions . front ( ) ; E ; E = E - > next ( ) ) {
if ( p_resource - > is_class ( " Script " ) & & ( E - > get ( ) = = " tres " | | E - > get ( ) = = " res " ) ) {
2015-12-31 17:12:27 +01:00
//this serves no purpose and confused people
continue ;
}
2020-12-13 02:37:23 +01:00
file - > add_filter ( " *. " + E - > get ( ) + " ; " + E - > get ( ) . to_upper ( ) ) ;
preferred . push_back ( E - > get ( ) ) ;
}
// Lowest priority extension
List < String > : : Element * res_element = preferred . find ( " res " ) ;
if ( res_element ) {
preferred . move_to_back ( res_element ) ;
}
// Highest priority extension
List < String > : : Element * tres_element = preferred . find ( " tres " ) ;
if ( tres_element ) {
preferred . move_to_front ( tres_element ) ;
2015-09-01 05:49:47 +02:00
}
2017-03-05 16:44:50 +01:00
if ( p_at_path ! = String ( ) ) {
2016-05-11 16:46:08 +02:00
file - > set_current_dir ( p_at_path ) ;
if ( p_resource - > get_path ( ) . is_resource_file ( ) ) {
file - > set_current_file ( p_resource - > get_path ( ) . get_file ( ) ) ;
} else {
2017-03-05 16:44:50 +01:00
if ( extensions . size ( ) ) {
file - > set_current_file ( " new_ " + p_resource - > get_class ( ) . to_lower ( ) + " . " + preferred . front ( ) - > get ( ) . to_lower ( ) ) ;
2016-05-11 16:46:08 +02:00
} else {
file - > set_current_file ( String ( ) ) ;
}
}
2017-03-05 16:44:50 +01:00
} else if ( p_resource - > get_path ( ) ! = " " ) {
2015-09-01 05:49:47 +02:00
file - > set_current_path ( p_resource - > get_path ( ) ) ;
if ( extensions . size ( ) ) {
2017-03-05 16:44:50 +01:00
String ext = p_resource - > get_path ( ) . get_extension ( ) . to_lower ( ) ;
2021-05-04 16:00:45 +02:00
if ( extensions . find ( ext ) = = nullptr ) {
2017-03-05 16:44:50 +01:00
file - > set_current_path ( p_resource - > get_path ( ) . replacen ( " . " + ext , " . " + extensions . front ( ) - > get ( ) ) ) ;
2015-09-01 05:49:47 +02:00
}
}
2015-12-31 17:12:27 +01:00
} else if ( preferred . size ( ) ) {
2015-09-01 05:49:47 +02:00
String existing ;
if ( extensions . size ( ) ) {
2017-03-05 16:44:50 +01:00
existing = " new_ " + p_resource - > get_class ( ) . to_lower ( ) + " . " + preferred . front ( ) - > get ( ) . to_lower ( ) ;
2015-09-01 05:49:47 +02:00
}
file - > set_current_path ( existing ) ;
}
file - > popup_centered_ratio ( ) ;
2018-04-22 19:36:01 +02:00
file - > set_title ( TTR ( " Save Resource As... " ) ) ;
2014-02-10 02:10:30 +01:00
}
void EditorNode : : _menu_option ( int p_option ) {
2017-03-05 16:44:50 +01:00
_menu_option_confirm ( p_option , false ) ;
2014-02-10 02:10:30 +01:00
}
void EditorNode : : _menu_confirm_current ( ) {
2017-03-05 16:44:50 +01:00
_menu_option_confirm ( current_option , true ) ;
2014-02-10 02:10:30 +01:00
}
2017-08-28 05:24:50 +02:00
void EditorNode : : _dialog_display_save_error ( String p_file , Error p_error ) {
2014-02-10 02:10:30 +01:00
if ( p_error ) {
2017-03-05 16:44:50 +01:00
switch ( p_error ) {
2014-02-10 02:10:30 +01:00
case ERR_FILE_CANT_WRITE : {
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " Can't open file for writing: " ) + " " + p_file . get_extension ( ) , TTR ( " OK " ) ) ;
2014-02-10 02:10:30 +01:00
} break ;
case ERR_FILE_UNRECOGNIZED : {
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " Requested file format unknown: " ) + " " + p_file . get_extension ( ) , TTR ( " OK " ) ) ;
2014-02-10 02:10:30 +01:00
} break ;
default : {
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " Error while saving. " ) , TTR ( " OK " ) ) ;
2017-03-05 16:44:50 +01:00
} break ;
2014-02-10 02:10:30 +01:00
}
}
}
2017-08-28 05:24:50 +02:00
void EditorNode : : _dialog_display_load_error ( String p_file , Error p_error ) {
if ( p_error ) {
switch ( p_error ) {
case ERR_CANT_OPEN : {
2018-08-05 16:47:41 +02:00
show_accept ( vformat ( TTR ( " Can't open '%s'. The file could have been moved or deleted. " ) , p_file . get_file ( ) ) , TTR ( " OK " ) ) ;
2017-08-28 05:24:50 +02:00
} break ;
case ERR_PARSE_ERROR : {
2018-08-05 16:47:41 +02:00
show_accept ( vformat ( TTR ( " Error while parsing '%s'. " ) , p_file . get_file ( ) ) , TTR ( " OK " ) ) ;
2017-08-28 05:24:50 +02:00
} break ;
case ERR_FILE_CORRUPT : {
2018-08-05 16:47:41 +02:00
show_accept ( vformat ( TTR ( " Unexpected end of file '%s'. " ) , p_file . get_file ( ) ) , TTR ( " OK " ) ) ;
2017-08-28 05:24:50 +02:00
} break ;
case ERR_FILE_NOT_FOUND : {
2018-08-05 16:47:41 +02:00
show_accept ( vformat ( TTR ( " Missing '%s' or its dependencies. " ) , p_file . get_file ( ) ) , TTR ( " OK " ) ) ;
2017-08-28 05:24:50 +02:00
} break ;
default : {
2018-08-05 16:47:41 +02:00
show_accept ( vformat ( TTR ( " Error while loading '%s'. " ) , p_file . get_file ( ) ) , TTR ( " OK " ) ) ;
2017-08-28 05:24:50 +02:00
} break ;
}
}
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _get_scene_metadata ( const String & p_file ) {
2015-06-22 05:03:19 +02:00
Node * scene = editor_data . get_edited_scene_root ( ) ;
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( ! scene ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-11-17 15:50:18 +01:00
String path = EditorSettings : : get_singleton ( ) - > get_project_settings_dir ( ) . plus_file ( p_file . get_file ( ) + " -editstate- " + p_file . md5_text ( ) + " .cfg " ) ;
2014-02-10 02:10:30 +01:00
2015-12-31 04:31:00 +01:00
Ref < ConfigFile > cf ;
cf . instance ( ) ;
2014-02-10 02:10:30 +01:00
2015-12-31 04:31:00 +01:00
Error err = cf - > load ( path ) ;
2021-05-05 12:44:11 +02:00
if ( err ! = OK | | ! cf - > has_section ( " editor_states " ) ) {
2015-12-31 04:31:00 +01:00
return ; //must not exist
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2015-12-31 04:31:00 +01:00
List < String > esl ;
2017-03-05 16:44:50 +01:00
cf - > get_section_keys ( " editor_states " , & esl ) ;
2014-02-10 02:10:30 +01:00
2015-12-31 04:31:00 +01:00
Dictionary md ;
2017-03-05 16:44:50 +01:00
for ( List < String > : : Element * E = esl . front ( ) ; E ; E = E - > next ( ) ) {
Variant st = cf - > get_value ( " editor_states " , E - > get ( ) ) ;
2019-07-20 08:09:57 +02:00
if ( st . get_type ( ) ! = Variant : : NIL ) {
2017-03-05 16:44:50 +01:00
md [ E - > get ( ) ] = st ;
2015-12-31 04:31:00 +01:00
}
2014-02-10 02:10:30 +01:00
}
2015-12-31 04:31:00 +01:00
editor_data . set_editor_states ( md ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _set_scene_metadata ( const String & p_file , int p_idx ) {
2016-06-26 05:54:17 +02:00
Node * scene = editor_data . get_edited_scene_root ( p_idx ) ;
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( ! scene ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
scene - > set_meta ( " __editor_run_settings__ " , Variant ( ) ) ; //clear it (no point in keeping it)
scene - > set_meta ( " __editor_plugin_states__ " , Variant ( ) ) ;
2014-02-10 02:10:30 +01:00
2017-11-17 15:50:18 +01:00
String path = EditorSettings : : get_singleton ( ) - > get_project_settings_dir ( ) . plus_file ( p_file . get_file ( ) + " -editstate- " + p_file . md5_text ( ) + " .cfg " ) ;
2014-02-10 02:10:30 +01:00
2015-12-31 04:31:00 +01:00
Ref < ConfigFile > cf ;
cf . instance ( ) ;
2014-02-10 02:10:30 +01:00
2016-07-17 21:59:15 +02:00
Dictionary md ;
2017-03-05 16:44:50 +01:00
if ( p_idx < 0 | | editor_data . get_edited_scene ( ) = = p_idx ) {
2016-07-17 21:59:15 +02:00
md = editor_data . get_editor_states ( ) ;
} else {
md = editor_data . get_scene_editor_states ( p_idx ) ;
}
2015-12-31 04:31:00 +01:00
List < Variant > keys ;
md . get_key_list ( & keys ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( List < Variant > : : Element * E = keys . front ( ) ; E ; E = E - > next ( ) ) {
cf - > set_value ( " editor_states " , E - > get ( ) , md [ E - > get ( ) ] ) ;
2015-12-31 04:31:00 +01:00
}
2014-02-10 02:10:30 +01:00
2015-12-31 04:31:00 +01:00
Error err = cf - > save ( path ) ;
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( err ! = OK , " Cannot save config file to ' " + path + " '. " ) ;
2014-02-10 02:10:30 +01:00
}
2017-08-12 18:52:50 +02:00
bool EditorNode : : _find_and_save_resource ( RES p_res , Map < RES , bool > & processed , int32_t flags ) {
2021-05-05 12:44:11 +02:00
if ( p_res . is_null ( ) ) {
2015-05-17 18:11:55 +02:00
return false ;
2021-05-05 12:44:11 +02:00
}
2015-05-17 18:11:55 +02:00
2017-08-12 18:52:50 +02:00
if ( processed . has ( p_res ) ) {
return processed [ p_res ] ;
2017-03-05 16:44:50 +01:00
}
2015-05-17 18:11:55 +02:00
2017-08-12 18:52:50 +02:00
bool changed = p_res - > is_edited ( ) ;
p_res - > set_edited ( false ) ;
2015-05-17 18:11:55 +02:00
2017-08-12 18:52:50 +02:00
bool subchanged = _find_and_save_edited_subresources ( p_res . ptr ( ) , processed , flags ) ;
2015-05-17 18:11:55 +02:00
2017-08-12 18:52:50 +02:00
if ( p_res - > get_path ( ) . is_resource_file ( ) ) {
2015-05-17 18:11:55 +02:00
if ( changed | | subchanged ) {
//save
2017-08-12 18:52:50 +02:00
ResourceSaver : : save ( p_res - > get_path ( ) , p_res , flags ) ;
2015-05-17 18:11:55 +02:00
}
2017-08-12 18:52:50 +02:00
processed [ p_res ] = false ; //because it's a file
2015-05-17 18:11:55 +02:00
return false ;
} else {
2017-08-12 18:52:50 +02:00
processed [ p_res ] = changed ;
2015-05-17 18:11:55 +02:00
return changed ;
}
}
2017-03-05 16:44:50 +01:00
bool EditorNode : : _find_and_save_edited_subresources ( Object * obj , Map < RES , bool > & processed , int32_t flags ) {
bool ret_changed = false ;
2014-02-10 02:10:30 +01:00
List < PropertyInfo > pi ;
obj - > get_property_list ( & pi ) ;
2017-03-05 16:44:50 +01:00
for ( List < PropertyInfo > : : Element * E = pi . front ( ) ; E ; E = E - > next ( ) ) {
2021-05-05 12:44:11 +02:00
if ( ! ( E - > get ( ) . usage & PROPERTY_USAGE_STORAGE ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
switch ( E - > get ( ) . type ) {
2014-02-10 02:10:30 +01:00
case Variant : : OBJECT : {
RES res = obj - > get ( E - > get ( ) . name ) ;
2021-05-05 12:44:11 +02:00
if ( _find_and_save_resource ( res , processed , flags ) ) {
2017-03-05 16:44:50 +01:00
ret_changed = true ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
} break ;
case Variant : : ARRAY : {
2017-03-05 16:44:50 +01:00
Array varray = obj - > get ( E - > get ( ) . name ) ;
int len = varray . size ( ) ;
for ( int i = 0 ; i < len ; i + + ) {
2019-12-10 05:13:02 +01:00
const Variant & v = varray . get ( i ) ;
2017-03-05 16:44:50 +01:00
RES res = v ;
2021-05-05 12:44:11 +02:00
if ( _find_and_save_resource ( res , processed , flags ) ) {
2017-03-05 16:44:50 +01:00
ret_changed = true ;
2021-05-05 12:44:11 +02:00
}
2015-05-17 18:11:55 +02:00
}
2014-02-10 02:10:30 +01:00
} break ;
case Variant : : DICTIONARY : {
2017-03-05 16:44:50 +01:00
Dictionary d = obj - > get ( E - > get ( ) . name ) ;
2014-02-10 02:10:30 +01:00
List < Variant > keys ;
d . get_key_list ( & keys ) ;
2019-02-12 21:10:08 +01:00
for ( List < Variant > : : Element * F = keys . front ( ) ; F ; F = F - > next ( ) ) {
Variant v = d [ F - > get ( ) ] ;
2017-03-05 16:44:50 +01:00
RES res = v ;
2021-05-05 12:44:11 +02:00
if ( _find_and_save_resource ( res , processed , flags ) ) {
2017-03-05 16:44:50 +01:00
ret_changed = true ;
2021-05-05 12:44:11 +02:00
}
2015-05-17 18:11:55 +02:00
}
2014-02-10 02:10:30 +01:00
} break ;
2019-04-09 17:08:36 +02:00
default : {
}
2014-02-10 02:10:30 +01:00
}
}
return ret_changed ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _save_edited_subresources ( Node * scene , Map < RES , bool > & processed , int32_t flags ) {
_find_and_save_edited_subresources ( scene , processed , flags ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < scene - > get_child_count ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
Node * n = scene - > get_child ( i ) ;
2021-05-05 12:44:11 +02:00
if ( n - > get_owner ( ) ! = editor_data . get_edited_scene_root ( ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
_save_edited_subresources ( n , processed , flags ) ;
2014-02-10 02:10:30 +01:00
}
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _find_node_types ( Node * p_node , int & count_2d , int & count_3d ) {
2021-05-05 12:44:11 +02:00
if ( p_node - > is_class ( " Viewport " ) | | ( p_node ! = editor_data . get_edited_scene_root ( ) & & p_node - > get_owner ( ) ! = editor_data . get_edited_scene_root ( ) ) ) {
2015-05-31 06:59:42 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-05-31 06:59:42 +02:00
2021-05-05 12:44:11 +02:00
if ( p_node - > is_class ( " CanvasItem " ) ) {
2015-05-31 06:59:42 +02:00
count_2d + + ;
2021-05-05 12:44:11 +02:00
} else if ( p_node - > is_class ( " Spatial " ) ) {
2015-05-31 06:59:42 +02:00
count_3d + + ;
2021-05-05 12:44:11 +02:00
}
2015-05-31 06:59:42 +02:00
2021-05-05 12:44:11 +02:00
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
2017-03-05 16:44:50 +01:00
_find_node_types ( p_node - > get_child ( i ) , count_2d , count_3d ) ;
2021-05-05 12:44:11 +02:00
}
2015-05-31 06:59:42 +02:00
}
2017-11-12 04:48:00 +01:00
void EditorNode : : _save_scene_with_preview ( String p_file , int p_idx ) {
2017-03-05 16:44:50 +01:00
EditorProgress save ( " save " , TTR ( " Saving Scene " ) , 4 ) ;
2017-08-26 17:46:49 +02:00
2021-05-04 16:00:45 +02:00
if ( editor_data . get_edited_scene_root ( ) ! = nullptr ) {
2019-12-26 09:15:36 +01:00
save . step ( TTR ( " Analyzing " ) , 0 ) ;
2015-05-31 06:59:42 +02:00
2019-12-26 09:15:36 +01:00
int c2d = 0 ;
int c3d = 0 ;
2017-06-09 05:23:50 +02:00
2019-12-26 09:15:36 +01:00
_find_node_types ( editor_data . get_edited_scene_root ( ) , c2d , c3d ) ;
2015-05-31 06:59:42 +02:00
2019-12-26 09:15:36 +01:00
save . step ( TTR ( " Creating Thumbnail " ) , 1 ) ;
//current view?
2019-01-27 17:39:16 +01:00
2019-12-26 09:15:36 +01:00
Ref < Image > img ;
2020-07-06 17:55:07 +02:00
// If neither 3D or 2D nodes are present, make a 1x1 black texture.
// We cannot fallback on the 2D editor, because it may not have been used yet,
// which would result in an invalid texture.
if ( c3d = = 0 & & c2d = = 0 ) {
img . instance ( ) ;
2021-05-04 16:28:24 +02:00
img - > create ( 1 , 1 , false , Image : : FORMAT_RGB8 ) ;
2020-07-06 17:55:07 +02:00
} else if ( c3d < c2d ) {
2020-07-27 15:49:56 +02:00
Ref < ViewportTexture > viewport_texture = scene_root - > get_texture ( ) ;
if ( viewport_texture - > get_width ( ) > 0 & & viewport_texture - > get_height ( ) > 0 ) {
img = viewport_texture - > get_data ( ) ;
}
2019-12-26 09:15:36 +01:00
} else {
2020-07-06 17:55:07 +02:00
// The 3D editor may be disabled as a feature, but scenes can still be opened.
// This check prevents the preview from regenerating in case those scenes are then saved.
2021-03-19 20:54:29 +01:00
// The preview will be generated if no feature profile is set (as the 3D editor is enabled by default).
2020-07-06 17:55:07 +02:00
Ref < EditorFeatureProfile > profile = feature_profile_manager - > get_current_profile ( ) ;
2021-03-19 20:54:29 +01:00
if ( ! profile . is_valid ( ) | | ! profile - > is_feature_disabled ( EditorFeatureProfile : : FEATURE_3D ) ) {
2020-07-06 17:55:07 +02:00
img = SpatialEditor : : get_singleton ( ) - > get_editor_viewport ( 0 ) - > get_viewport_node ( ) - > get_texture ( ) - > get_data ( ) ;
}
2019-12-26 09:15:36 +01:00
}
2019-01-27 17:39:16 +01:00
2020-07-27 15:49:56 +02:00
if ( img . is_valid ( ) & & img - > get_width ( ) > 0 & & img - > get_height ( ) > 0 ) {
2019-12-26 09:15:36 +01:00
img = img - > duplicate ( ) ;
2015-05-31 06:59:42 +02:00
2019-12-26 09:15:36 +01:00
save . step ( TTR ( " Creating Thumbnail " ) , 2 ) ;
save . step ( TTR ( " Creating Thumbnail " ) , 3 ) ;
2015-05-31 06:59:42 +02:00
2019-12-26 09:15:36 +01:00
int preview_size = EditorSettings : : get_singleton ( ) - > get ( " filesystem/file_dialog/thumbnail_size " ) ;
preview_size * = EDSCALE ;
2015-05-31 06:59:42 +02:00
2019-12-26 09:15:36 +01:00
// consider a square region
int vp_size = MIN ( img - > get_width ( ) , img - > get_height ( ) ) ;
int x = ( img - > get_width ( ) - vp_size ) / 2 ;
int y = ( img - > get_height ( ) - vp_size ) / 2 ;
2017-11-18 04:42:14 +01:00
2019-12-26 09:15:36 +01:00
if ( vp_size < preview_size ) {
// just square it.
img - > crop_from_point ( x , y , vp_size , vp_size ) ;
} else {
int ratio = vp_size / preview_size ;
int size = preview_size * MAX ( 1 , ratio / 2 ) ;
2015-05-31 06:59:42 +02:00
2019-12-26 09:15:36 +01:00
x = ( img - > get_width ( ) - size ) / 2 ;
y = ( img - > get_height ( ) - size ) / 2 ;
2015-05-31 06:59:42 +02:00
2019-12-26 09:15:36 +01:00
img - > crop_from_point ( x , y , size , size ) ;
img - > resize ( preview_size , preview_size , Image : : INTERPOLATE_LANCZOS ) ;
}
img - > convert ( Image : : FORMAT_RGB8 ) ;
2015-05-31 06:59:42 +02:00
2019-12-26 09:15:36 +01:00
img - > flip_y ( ) ;
2015-05-31 06:59:42 +02:00
2019-12-26 09:15:36 +01:00
//save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5
String temp_path = EditorSettings : : get_singleton ( ) - > get_cache_dir ( ) ;
String cache_base = ProjectSettings : : get_singleton ( ) - > globalize_path ( p_file ) . md5_text ( ) ;
cache_base = temp_path . plus_file ( " resthumb- " + cache_base ) ;
2017-06-09 05:23:50 +02:00
2019-12-26 09:15:36 +01:00
//does not have it, try to load a cached thumbnail
String file = cache_base + " .png " ;
post_process_preview ( img ) ;
img - > save_png ( file ) ;
}
2015-05-31 06:59:42 +02:00
}
2017-06-09 05:23:50 +02:00
2017-03-05 16:44:50 +01:00
save . step ( TTR ( " Saving Scene " ) , 4 ) ;
2017-11-12 04:48:00 +01:00
_save_scene ( p_file , p_idx ) ;
2020-01-14 11:32:15 +01:00
if ( ! singleton - > cmdline_export_mode ) {
EditorResourcePreview : : get_singleton ( ) - > check_for_invalidation ( p_file ) ;
}
2015-05-31 06:59:42 +02:00
}
2018-11-27 22:56:31 +01:00
bool EditorNode : : _validate_scene_recursive ( const String & p_filename , Node * p_node ) {
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
Node * child = p_node - > get_child ( i ) ;
if ( child - > get_filename ( ) = = p_filename ) {
return true ;
}
if ( _validate_scene_recursive ( p_filename , child ) ) {
return true ;
}
}
return false ;
}
2019-02-28 00:00:40 +01:00
int EditorNode : : _save_external_resources ( ) {
//save external resources and its subresources if any was modified
int flg = 0 ;
2021-05-05 12:44:11 +02:00
if ( EditorSettings : : get_singleton ( ) - > get ( " filesystem/on_save/compress_binary_resources " ) ) {
2019-02-28 00:00:40 +01:00
flg | = ResourceSaver : : FLAG_COMPRESS ;
2021-05-05 12:44:11 +02:00
}
2019-02-28 00:00:40 +01:00
flg | = ResourceSaver : : FLAG_REPLACE_SUBRESOURCE_PATHS ;
2022-06-22 19:03:43 +02:00
Set < String > edited_resources ;
2019-02-28 00:00:40 +01:00
int saved = 0 ;
2021-05-04 14:20:36 +02:00
List < Ref < Resource > > cached ;
2019-02-28 00:00:40 +01:00
ResourceCache : : get_cached_resources ( & cached ) ;
2021-05-04 14:20:36 +02:00
for ( List < Ref < Resource > > : : Element * E = cached . front ( ) ; E ; E = E - > next ( ) ) {
2019-02-28 00:00:40 +01:00
Ref < Resource > res = E - > get ( ) ;
2022-06-22 19:03:43 +02:00
if ( ! res - > is_edited ( ) ) {
2019-02-28 00:00:40 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2019-02-28 00:00:40 +01:00
2022-06-22 19:03:43 +02:00
String path = res - > get_path ( ) ;
if ( path . begins_with ( " res:// " ) ) {
int subres_pos = path . find ( " :: " ) ;
if ( subres_pos = = - 1 ) {
// Actual resource.
edited_resources . insert ( path ) ;
} else {
edited_resources . insert ( path . substr ( 0 , subres_pos ) ) ;
}
}
2019-02-28 00:00:40 +01:00
res - > set_edited ( false ) ;
}
2022-06-22 19:03:43 +02:00
for ( Set < String > : : Element * E = edited_resources . front ( ) ; E ; E = E - > next ( ) ) {
Ref < Resource > res = Ref < Resource > ( ResourceCache : : get ( E - > get ( ) ) ) ;
if ( ! res . is_valid ( ) ) {
continue ; // Maybe it was erased in a thread, who knows.
}
Ref < PackedScene > ps = res ;
if ( ps . is_valid ( ) ) {
continue ; // Do not save PackedScenes, this will mess up the editor.
}
ResourceSaver : : save ( res - > get_path ( ) , res , flg ) ;
saved + + ;
}
2019-02-28 00:00:40 +01:00
return saved ;
}
2020-12-20 11:46:44 +01:00
static void _reset_animation_players ( Node * p_node , List < Ref < AnimatedValuesBackup > > * r_anim_backups ) {
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
AnimationPlayer * player = Object : : cast_to < AnimationPlayer > ( p_node - > get_child ( i ) ) ;
if ( player & & player - > is_reset_on_save_enabled ( ) & & player - > can_apply_reset ( ) ) {
Ref < AnimatedValuesBackup > old_values = player - > apply_reset ( ) ;
2021-08-12 04:53:35 +02:00
if ( old_values . is_valid ( ) ) {
r_anim_backups - > push_back ( old_values ) ;
}
2020-12-20 11:46:44 +01:00
}
_reset_animation_players ( p_node - > get_child ( i ) , r_anim_backups ) ;
}
}
2016-06-26 05:54:17 +02:00
void EditorNode : : _save_scene ( String p_file , int idx ) {
Node * scene = editor_data . get_edited_scene_root ( idx ) ;
2014-02-10 02:10:30 +01:00
if ( ! scene ) {
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " This operation can't be done without a tree root. " ) , TTR ( " OK " ) ) ;
2014-02-10 02:10:30 +01:00
return ;
}
2018-11-27 22:56:31 +01:00
if ( scene - > get_filename ( ) ! = String ( ) & & _validate_scene_recursive ( scene - > get_filename ( ) , scene ) ) {
show_accept ( TTR ( " This scene can't be saved because there is a cyclic instancing inclusion. \n Please resolve it and then attempt to save again. " ) , TTR ( " OK " ) ) ;
return ;
}
2014-02-10 02:10:30 +01:00
editor_data . apply_changes_in_editors ( ) ;
2020-12-20 11:46:44 +01:00
List < Ref < AnimatedValuesBackup > > anim_backups ;
_reset_animation_players ( scene , & anim_backups ) ;
2017-05-29 02:46:48 +02:00
_save_default_environment ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
_set_scene_metadata ( p_file , idx ) ;
2015-12-14 00:39:01 +01:00
Ref < PackedScene > sdata ;
if ( ResourceCache : : has ( p_file ) ) {
// something may be referencing this resource and we are good with that.
// we must update it, but also let the previous scene state go, as
// old version still work for referencing changes in instanced or inherited scenes
2017-08-24 22:58:51 +02:00
sdata = Ref < PackedScene > ( Object : : cast_to < PackedScene > ( ResourceCache : : get ( p_file ) ) ) ;
2021-05-05 12:44:11 +02:00
if ( sdata . is_valid ( ) ) {
2015-12-14 00:39:01 +01:00
sdata - > recreate_state ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2015-12-14 00:39:01 +01:00
sdata . instance ( ) ;
2021-05-05 12:44:11 +02:00
}
2015-12-14 00:39:01 +01:00
} else {
sdata . instance ( ) ;
}
2014-02-10 02:10:30 +01:00
Error err = sdata - > pack ( scene ) ;
2017-03-05 16:44:50 +01:00
if ( err ! = OK ) {
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied. " ) , TTR ( " OK " ) ) ;
2014-02-10 02:10:30 +01:00
return ;
}
2017-03-05 16:44:50 +01:00
int flg = 0 ;
2021-05-05 12:44:11 +02:00
if ( EditorSettings : : get_singleton ( ) - > get ( " filesystem/on_save/compress_binary_resources " ) ) {
2017-03-05 16:44:50 +01:00
flg | = ResourceSaver : : FLAG_COMPRESS ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
flg | = ResourceSaver : : FLAG_REPLACE_SUBRESOURCE_PATHS ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
err = ResourceSaver : : save ( p_file , sdata , flg ) ;
2019-02-27 03:48:30 +01:00
2021-12-04 01:12:52 +01:00
// This needs to be emitted before saving external resources.
emit_signal ( " scene_saved " , p_file ) ;
2018-07-01 22:44:15 +02:00
2021-12-04 01:12:52 +01:00
_save_external_resources ( ) ;
2014-02-10 02:10:30 +01:00
editor_data . save_editor_external_data ( ) ;
2020-12-20 11:46:44 +01:00
for ( List < Ref < AnimatedValuesBackup > > : : Element * E = anim_backups . front ( ) ; E ; E = E - > next ( ) ) {
E - > get ( ) - > restore ( ) ;
}
2017-03-05 16:44:50 +01:00
if ( err = = OK ) {
2017-07-19 22:00:46 +02:00
scene - > set_filename ( ProjectSettings : : get_singleton ( ) - > localize_path ( p_file ) ) ;
2021-05-05 12:44:11 +02:00
if ( idx < 0 | | idx = = editor_data . get_edited_scene ( ) ) {
2016-06-26 05:54:17 +02:00
set_current_version ( editor_data . get_undo_redo ( ) . get_version ( ) ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-03-05 16:44:50 +01:00
editor_data . set_edited_scene_version ( 0 , idx ) ;
2021-05-05 12:44:11 +02:00
}
2021-02-11 01:08:49 +01:00
editor_data . set_scene_modified_time ( idx , FileAccess : : get_modified_time ( p_file ) ) ;
2018-10-29 20:36:31 +01:00
editor_folding . save_scene_folding ( scene , p_file ) ;
2014-02-10 02:10:30 +01:00
_update_title ( ) ;
2015-08-12 22:35:37 +02:00
_update_scene_tabs ( ) ;
2014-02-10 02:10:30 +01:00
} else {
2017-08-28 05:24:50 +02:00
_dialog_display_save_error ( p_file , err ) ;
2014-02-10 02:10:30 +01:00
}
2017-05-29 02:46:48 +02:00
}
2014-02-10 02:10:30 +01:00
2019-01-25 21:23:56 +01:00
void EditorNode : : save_all_scenes ( ) {
2018-07-19 23:58:15 +02:00
_menu_option_confirm ( RUN_STOP , true ) ;
_save_all_scenes ( ) ;
2019-01-25 21:23:56 +01:00
}
2019-06-04 05:36:23 +02:00
void EditorNode : : save_scene_list ( Vector < String > p_scene_filenames ) {
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
Node * scene = editor_data . get_edited_scene_root ( i ) ;
if ( scene & & ( p_scene_filenames . find ( scene - > get_filename ( ) ) > = 0 ) ) {
_save_scene ( scene - > get_filename ( ) , i ) ;
}
}
}
2019-01-25 21:23:56 +01:00
void EditorNode : : restart_editor ( ) {
exiting = true ;
2018-07-19 23:58:15 +02:00
2022-06-17 02:20:37 +02:00
if ( editor_run . get_status ( ) ! = EditorRun : : STATUS_STOP ) {
editor_run . stop ( ) ;
}
2018-07-19 23:58:15 +02:00
String to_reopen ;
if ( get_tree ( ) - > get_edited_scene_root ( ) ) {
to_reopen = get_tree ( ) - > get_edited_scene_root ( ) - > get_filename ( ) ;
}
2019-01-17 13:09:01 +01:00
_exit_editor ( ) ;
2018-07-19 23:58:15 +02:00
List < String > args ;
2022-07-26 19:07:06 +02:00
2022-08-13 21:52:03 +02:00
const Vector < String > & forwardable_args = Main : : get_forwardable_cli_arguments ( Main : : CLI_SCOPE_TOOL ) ;
for ( int i = 0 ; i < forwardable_args . size ( ) ; i + + ) {
args . push_back ( forwardable_args [ i ] ) ;
}
2018-07-19 23:58:15 +02:00
args . push_back ( " --path " ) ;
args . push_back ( ProjectSettings : : get_singleton ( ) - > get_resource_path ( ) ) ;
2022-07-26 19:07:06 +02:00
2018-07-19 23:58:15 +02:00
args . push_back ( " -e " ) ;
2022-07-26 19:07:06 +02:00
2018-07-19 23:58:15 +02:00
if ( to_reopen ! = String ( ) ) {
args . push_back ( to_reopen ) ;
}
OS : : get_singleton ( ) - > set_restart_on_exit ( true , args ) ;
}
2017-06-24 12:57:30 +02:00
void EditorNode : : _save_all_scenes ( ) {
2021-10-12 12:14:02 +02:00
bool all_saved = true ;
2018-06-29 08:38:15 +02:00
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
2017-06-24 12:57:30 +02:00
Node * scene = editor_data . get_edited_scene_root ( i ) ;
2021-10-12 12:14:02 +02:00
if ( scene ) {
if ( scene - > get_filename ( ) ! = " " & & DirAccess : : exists ( scene - > get_filename ( ) . get_base_dir ( ) ) ) {
if ( i ! = editor_data . get_edited_scene ( ) ) {
_save_scene ( scene - > get_filename ( ) , i ) ;
} else {
_save_scene_with_preview ( scene - > get_filename ( ) ) ;
}
2021-11-07 16:38:56 +01:00
} else if ( scene - > get_filename ( ) ! = " " ) {
2021-10-12 12:14:02 +02:00
all_saved = false ;
2021-05-05 12:44:11 +02:00
}
2021-09-11 03:35:13 +02:00
}
2017-06-24 12:57:30 +02:00
}
2021-10-12 12:14:02 +02:00
if ( ! all_saved ) {
show_warning ( TTR ( " Could not save one or more scenes! " ) , TTR ( " Save All Scenes " ) ) ;
}
2017-06-24 12:57:30 +02:00
_save_default_environment ( ) ;
}
2017-06-29 19:37:54 +02:00
void EditorNode : : _mark_unsaved_scenes ( ) {
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
Node * node = editor_data . get_edited_scene_root ( i ) ;
2021-05-05 12:44:11 +02:00
if ( ! node ) {
2017-06-29 19:37:54 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2017-06-29 19:37:54 +02:00
String path = node - > get_filename ( ) ;
if ( ! ( path = = String ( ) | | FileAccess : : exists ( path ) ) ) {
2021-05-05 12:44:11 +02:00
if ( i = = editor_data . get_edited_scene ( ) ) {
2017-06-29 19:37:54 +02:00
set_current_version ( - 1 ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-06-29 19:37:54 +02:00
editor_data . set_edited_scene_version ( - 1 , i ) ;
2021-05-05 12:44:11 +02:00
}
2017-06-29 19:37:54 +02:00
}
}
_update_title ( ) ;
_update_scene_tabs ( ) ;
}
2014-02-10 02:10:30 +01:00
void EditorNode : : _dialog_action ( String p_file ) {
2017-03-05 16:44:50 +01:00
switch ( current_option ) {
2015-10-10 14:09:09 +02:00
case FILE_NEW_INHERITED_SCENE : {
2019-05-08 08:12:39 +02:00
Node * scene = editor_data . get_edited_scene_root ( ) ;
// If the previous scene is rootless, just close it in favor of the new one.
2021-05-05 12:44:11 +02:00
if ( ! scene ) {
2019-05-31 02:08:37 +02:00
_menu_option_confirm ( FILE_CLOSE , true ) ;
2021-05-05 12:44:11 +02:00
}
2019-05-08 08:12:39 +02:00
2017-03-05 16:44:50 +01:00
load_scene ( p_file , false , true ) ;
2015-10-10 14:09:09 +02:00
} break ;
2014-02-10 02:10:30 +01:00
case FILE_OPEN_SCENE : {
load_scene ( p_file ) ;
} break ;
2016-06-28 00:59:33 +02:00
case SETTINGS_PICK_MAIN_SCENE : {
2017-07-19 22:00:46 +02:00
ProjectSettings : : get_singleton ( ) - > set ( " application/run/main_scene " , p_file ) ;
ProjectSettings : : get_singleton ( ) - > save ( ) ;
2017-04-06 17:35:08 +02:00
//would be nice to show the project manager opened with the highlighted field..
2019-03-22 02:08:28 +01:00
if ( pick_main_scene - > has_meta ( " from_native " ) & & ( bool ) pick_main_scene - > get_meta ( " from_native " ) ) {
run_native - > resume_run_native ( ) ;
} else {
_run ( false , " " ) ; // automatically run the project
}
2014-02-10 02:10:30 +01:00
} break ;
2017-06-21 06:15:39 +02:00
case FILE_CLOSE :
2017-06-26 16:04:53 +02:00
case FILE_CLOSE_ALL_AND_QUIT :
case FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER :
2022-03-23 12:07:29 +01:00
case FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT :
2017-06-21 06:15:39 +02:00
case SCENE_TAB_CLOSE :
2014-02-10 02:10:30 +01:00
case FILE_SAVE_SCENE :
case FILE_SAVE_AS_SCENE : {
2017-06-26 16:04:53 +02:00
int scene_idx = ( current_option = = FILE_SAVE_SCENE | | current_option = = FILE_SAVE_AS_SCENE ) ? - 1 : tab_closing ;
2017-06-21 06:15:39 +02:00
2017-03-05 16:44:50 +01:00
if ( file - > get_mode ( ) = = EditorFileDialog : : MODE_SAVE_FILE ) {
2018-09-07 15:54:26 +02:00
bool same_open_scene = false ;
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( editor_data . get_scene_path ( i ) = = p_file & & i ! = scene_idx ) {
2018-09-07 15:54:26 +02:00
same_open_scene = true ;
2021-05-05 12:44:11 +02:00
}
2018-09-07 15:54:26 +02:00
}
if ( same_open_scene ) {
show_warning ( TTR ( " Can't overwrite scene that is still open! " ) ) ;
return ;
}
2014-02-10 02:10:30 +01:00
2017-05-29 02:46:48 +02:00
_save_default_environment ( ) ;
2017-11-12 04:48:00 +01:00
_save_scene_with_preview ( p_file , scene_idx ) ;
2018-01-09 13:42:45 +01:00
_add_to_recent_scenes ( p_file ) ;
2019-04-15 22:17:49 +02:00
save_layout ( ) ;
2017-06-21 06:15:39 +02:00
2021-05-05 12:44:11 +02:00
if ( scene_idx ! = - 1 ) {
2017-06-21 06:15:39 +02:00
_discard_changes ( ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
} break ;
2015-01-06 23:28:25 +01:00
case FILE_SAVE_AND_RUN : {
2017-03-05 16:44:50 +01:00
if ( file - > get_mode ( ) = = EditorFileDialog : : MODE_SAVE_FILE ) {
2017-05-29 02:46:48 +02:00
_save_default_environment ( ) ;
2015-05-31 06:59:42 +02:00
_save_scene_with_preview ( p_file ) ;
2017-11-19 22:59:05 +01:00
_run ( false , p_file ) ;
2015-01-06 23:28:25 +01:00
}
} break ;
2014-02-10 02:10:30 +01:00
case FILE_EXPORT_MESH_LIBRARY : {
Ref < MeshLibrary > ml ;
if ( file_export_lib_merge - > is_pressed ( ) & & FileAccess : : exists ( p_file ) ) {
2017-03-05 16:44:50 +01:00
ml = ResourceLoader : : load ( p_file , " MeshLibrary " ) ;
2014-02-10 02:10:30 +01:00
if ( ml . is_null ( ) ) {
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " Can't load MeshLibrary for merging! " ) , TTR ( " OK " ) ) ;
2014-02-10 02:10:30 +01:00
return ;
}
}
if ( ml . is_null ( ) ) {
2017-03-05 16:44:50 +01:00
ml = Ref < MeshLibrary > ( memnew ( MeshLibrary ) ) ;
2014-02-10 02:10:30 +01:00
}
2021-09-01 01:17:33 +02:00
MeshLibraryEditor : : update_library_file ( editor_data . get_edited_scene_root ( ) , ml , true , file_export_lib_apply_xforms - > is_pressed ( ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Error err = ResourceSaver : : save ( p_file , ml ) ;
2014-02-10 02:10:30 +01:00
if ( err ) {
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " Error saving MeshLibrary! " ) , TTR ( " OK " ) ) ;
2014-02-10 02:10:30 +01:00
return ;
}
} break ;
case FILE_EXPORT_TILESET : {
2018-03-11 15:59:50 +01:00
Ref < TileSet > tileset ;
if ( FileAccess : : exists ( p_file ) & & file_export_lib_merge - > is_pressed ( ) ) {
tileset = ResourceLoader : : load ( p_file , " TileSet " ) ;
2014-02-10 02:10:30 +01:00
2018-03-11 15:59:50 +01:00
if ( tileset . is_null ( ) ) {
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " Can't load TileSet for merging! " ) , TTR ( " OK " ) ) ;
2018-03-11 15:59:50 +01:00
return ;
2016-01-08 17:54:13 +01:00
}
2016-03-11 01:20:01 +01:00
} else {
2018-03-11 15:59:50 +01:00
tileset = Ref < TileSet > ( memnew ( TileSet ) ) ;
2014-02-10 02:10:30 +01:00
}
2018-03-11 15:59:50 +01:00
TileSetEditor : : update_library_file ( editor_data . get_edited_scene_root ( ) , tileset , true ) ;
2014-02-10 02:10:30 +01:00
2018-03-11 15:59:50 +01:00
Error err = ResourceSaver : : save ( p_file , tileset ) ;
2014-02-10 02:10:30 +01:00
if ( err ) {
2018-08-08 16:30:23 +02:00
show_accept ( TTR ( " Error saving TileSet! " ) , TTR ( " OK " ) ) ;
2014-02-10 02:10:30 +01:00
return ;
}
} break ;
2015-09-01 05:49:47 +02:00
case RESOURCE_SAVE :
case RESOURCE_SAVE_AS : {
2019-06-11 14:49:34 +02:00
ERR_FAIL_COND ( saving_resource . is_null ( ) ) ;
2018-11-18 15:17:04 +01:00
save_resource_in_path ( saving_resource , p_file ) ;
saving_resource = Ref < Resource > ( ) ;
ObjectID current = editor_history . get_current ( ) ;
2021-05-04 16:00:45 +02:00
Object * current_obj = current > 0 ? ObjectDB : : get_instance ( current ) : nullptr ;
2018-11-18 15:17:04 +01:00
ERR_FAIL_COND ( ! current_obj ) ;
current_obj - > _change_notify ( ) ;
2015-11-22 19:11:17 +01:00
} break ;
case SETTINGS_LAYOUT_SAVE : {
2021-05-05 12:44:11 +02:00
if ( p_file . empty ( ) ) {
2015-11-22 19:11:17 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-11-22 19:11:17 +01:00
Ref < ConfigFile > config ;
config . instance ( ) ;
2017-11-17 21:48:24 +01:00
Error err = config - > load ( EditorSettings : : get_singleton ( ) - > get_editor_layouts_config ( ) ) ;
2016-01-01 18:48:14 +01:00
2019-10-23 15:02:51 +02:00
if ( err = = ERR_FILE_CANT_OPEN | | err = = ERR_FILE_NOT_FOUND ) {
2016-01-01 18:48:14 +01:00
config . instance ( ) ; // new config
2017-03-05 16:44:50 +01:00
} else if ( err ! = OK ) {
2020-08-02 14:12:50 +02:00
show_warning ( TTR ( " An error occurred while trying to save the editor layout. \n Make sure the editor's user data path is writable. " ) ) ;
2016-01-01 18:48:14 +01:00
return ;
2015-11-22 19:11:17 +01:00
}
_save_docks_to_config ( config , p_file ) ;
2017-11-17 21:48:24 +01:00
config - > save ( EditorSettings : : get_singleton ( ) - > get_editor_layouts_config ( ) ) ;
2015-11-22 19:11:17 +01:00
layout_dialog - > hide ( ) ;
_update_layouts_menu ( ) ;
2017-03-05 16:44:50 +01:00
if ( p_file = = " Default " ) {
2020-08-02 14:12:50 +02:00
show_warning ( TTR ( " Default editor layout overridden. \n To restore the Default layout to its base settings, use the Delete Layout option and delete the Default layout. " ) ) ;
2016-01-11 22:23:45 +01:00
}
2015-11-22 19:11:17 +01:00
} break ;
case SETTINGS_LAYOUT_DELETE : {
2021-05-05 12:44:11 +02:00
if ( p_file . empty ( ) ) {
2015-11-22 19:11:17 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-11-22 19:11:17 +01:00
Ref < ConfigFile > config ;
config . instance ( ) ;
2017-11-17 21:48:24 +01:00
Error err = config - > load ( EditorSettings : : get_singleton ( ) - > get_editor_layouts_config ( ) ) ;
2015-11-22 19:11:17 +01:00
2017-03-05 16:44:50 +01:00
if ( err ! = OK | | ! config - > has_section ( p_file ) ) {
2016-05-04 03:25:37 +02:00
show_warning ( TTR ( " Layout name not found! " ) ) ;
2015-11-22 19:11:17 +01:00
return ;
}
// erase
List < String > keys ;
config - > get_section_keys ( p_file , & keys ) ;
2017-03-05 16:44:50 +01:00
for ( List < String > : : Element * E = keys . front ( ) ; E ; E = E - > next ( ) ) {
2015-11-22 19:11:17 +01:00
config - > set_value ( p_file , E - > get ( ) , Variant ( ) ) ;
}
2017-11-17 21:48:24 +01:00
config - > save ( EditorSettings : : get_singleton ( ) - > get_editor_layouts_config ( ) ) ;
2015-11-22 19:11:17 +01:00
layout_dialog - > hide ( ) ;
_update_layouts_menu ( ) ;
2017-03-05 16:44:50 +01:00
if ( p_file = = " Default " ) {
2020-08-02 14:12:50 +02:00
show_warning ( TTR ( " Restored the Default layout to its base settings. " ) ) ;
2016-01-11 22:23:45 +01:00
}
2015-09-01 05:49:47 +02:00
} break ;
2014-02-10 02:10:30 +01:00
default : { //save scene?
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
if ( file - > get_mode ( ) = = EditorFileDialog : : MODE_SAVE_FILE ) {
2015-05-31 06:59:42 +02:00
_save_scene_with_preview ( p_file ) ;
2014-02-10 02:10:30 +01:00
}
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
} break ;
}
}
2018-06-19 03:10:48 +02:00
bool EditorNode : : item_has_editor ( Object * p_object ) {
2019-04-09 00:18:03 +02:00
if ( _is_class_editor_disabled_by_feature_profile ( p_object - > get_class ( ) ) ) {
return false ;
}
2018-06-19 03:10:48 +02:00
return editor_data . get_subeditors ( p_object ) . size ( ) > 0 ;
}
2019-02-22 21:42:29 +01:00
void EditorNode : : edit_item_resource ( RES p_resource ) {
edit_item ( p_resource . ptr ( ) ) ;
}
2019-04-09 00:18:03 +02:00
bool EditorNode : : _is_class_editor_disabled_by_feature_profile ( const StringName & p_class ) {
Ref < EditorFeatureProfile > profile = EditorFeatureProfileManager : : get_singleton ( ) - > get_current_profile ( ) ;
if ( profile . is_null ( ) ) {
return false ;
}
StringName class_name = p_class ;
while ( class_name ! = StringName ( ) ) {
2019-04-09 01:20:20 +02:00
if ( profile - > is_class_disabled ( class_name ) ) {
return true ;
}
2019-04-09 00:18:03 +02:00
if ( profile - > is_class_editor_disabled ( class_name ) ) {
return true ;
}
class_name = ClassDB : : get_parent_class ( class_name ) ;
}
return false ;
}
2018-06-19 03:10:48 +02:00
void EditorNode : : edit_item ( Object * p_object ) {
2018-06-21 23:08:11 +02:00
Vector < EditorPlugin * > sub_plugins ;
if ( p_object ) {
2019-04-09 00:18:03 +02:00
if ( _is_class_editor_disabled_by_feature_profile ( p_object - > get_class ( ) ) ) {
return ;
}
2018-06-21 23:08:11 +02:00
sub_plugins = editor_data . get_subeditors ( p_object ) ;
}
2018-06-19 03:10:48 +02:00
if ( ! sub_plugins . empty ( ) ) {
2019-03-06 16:42:01 +01:00
bool same = true ;
if ( sub_plugins . size ( ) = = editor_plugins_over - > get_plugins_list ( ) . size ( ) ) {
for ( int i = 0 ; i < sub_plugins . size ( ) ; i + + ) {
if ( sub_plugins [ i ] ! = editor_plugins_over - > get_plugins_list ( ) [ i ] ) {
same = false ;
}
}
} else {
same = false ;
}
if ( ! same ) {
_display_top_editors ( false ) ;
_set_top_editors ( sub_plugins ) ;
}
2018-06-19 03:10:48 +02:00
_set_editing_top_editors ( p_object ) ;
_display_top_editors ( true ) ;
2018-06-21 23:08:11 +02:00
} else {
2019-03-04 20:44:39 +01:00
hide_top_editors ( ) ;
2018-06-19 03:10:48 +02:00
}
}
void EditorNode : : push_item ( Object * p_object , const String & p_property , bool p_inspector_only ) {
2014-02-10 02:10:30 +01:00
if ( ! p_object ) {
2021-05-04 16:00:45 +02:00
get_inspector ( ) - > edit ( nullptr ) ;
node_dock - > set_node ( nullptr ) ;
scene_tree_dock - > set_selected ( nullptr ) ;
inspector_dock - > update ( nullptr ) ;
2020-10-30 23:29:07 +01:00
_display_top_editors ( false ) ;
2014-02-10 02:10:30 +01:00
return ;
}
2017-08-07 12:17:31 +02:00
uint32_t id = p_object - > get_instance_id ( ) ;
2017-03-05 16:44:50 +01:00
if ( id ! = editor_history . get_current ( ) ) {
2018-06-19 03:10:48 +02:00
if ( p_inspector_only ) {
editor_history . add_object_inspector_only ( id ) ;
2021-05-05 12:44:11 +02:00
} else if ( p_property = = " " ) {
2014-02-10 02:10:30 +01:00
editor_history . add_object ( id ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-03-05 16:44:50 +01:00
editor_history . add_object ( id , p_property ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
_edit_current ( ) ;
}
2017-05-29 02:46:48 +02:00
void EditorNode : : _save_default_environment ( ) {
2017-05-30 03:11:33 +02:00
Ref < Environment > fallback = get_tree ( ) - > get_root ( ) - > get_world ( ) - > get_fallback_environment ( ) ;
2017-05-29 02:46:48 +02:00
if ( fallback . is_valid ( ) & & fallback - > get_path ( ) . is_resource_file ( ) ) {
Map < RES , bool > processed ;
_find_and_save_edited_subresources ( fallback . ptr ( ) , processed , 0 ) ;
2018-06-29 08:38:15 +02:00
save_resource_in_path ( fallback , fallback - > get_path ( ) ) ;
2017-05-29 02:46:48 +02:00
}
}
2019-03-04 20:44:39 +01:00
void EditorNode : : hide_top_editors ( ) {
2016-03-30 01:02:53 +02:00
_display_top_editors ( false ) ;
2014-02-10 02:10:30 +01:00
2016-03-30 01:02:53 +02:00
editor_plugins_over - > clear ( ) ;
}
void EditorNode : : _display_top_editors ( bool p_display ) {
editor_plugins_over - > make_visible ( p_display ) ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _set_top_editors ( Vector < EditorPlugin * > p_editor_plugins_over ) {
2016-03-30 01:02:53 +02:00
editor_plugins_over - > set_plugins_list ( p_editor_plugins_over ) ;
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
void EditorNode : : _set_editing_top_editors ( Object * p_current_object ) {
2016-03-30 01:02:53 +02:00
editor_plugins_over - > edit ( p_current_object ) ;
2014-02-10 02:10:30 +01:00
}
2017-09-03 21:23:36 +02:00
static bool overrides_external_editor ( Object * p_object ) {
Script * script = Object : : cast_to < Script > ( p_object ) ;
2021-05-05 12:44:11 +02:00
if ( ! script ) {
2017-09-03 21:23:36 +02:00
return false ;
2021-05-05 12:44:11 +02:00
}
2017-09-03 21:23:36 +02:00
return script - > get_language ( ) - > overrides_external_editor ( ) ;
}
2021-09-12 21:17:34 +02:00
void EditorNode : : _edit_current ( bool p_skip_foreign ) {
2014-02-10 02:10:30 +01:00
uint32_t current = editor_history . get_current ( ) ;
2021-05-04 16:00:45 +02:00
Object * current_obj = current > 0 ? ObjectDB : : get_instance ( current ) : nullptr ;
2014-02-10 02:10:30 +01:00
2021-09-12 21:17:34 +02:00
RES res = Object : : cast_to < Resource > ( current_obj ) ;
if ( p_skip_foreign & & res . is_valid ( ) ) {
if ( res - > get_path ( ) . find ( " :: " ) > - 1 & & res - > get_path ( ) . get_slice ( " :: " , 0 ) ! = editor_data . get_scene_path ( get_current_tab ( ) ) ) {
// Trying to edit resource that belongs to another scene; abort.
current_obj = nullptr ;
}
}
bool inspector_only = editor_history . is_current_inspector_only ( ) ;
2017-03-05 16:44:50 +01:00
this - > current = current_obj ;
2017-09-14 15:38:59 +02:00
2014-02-10 02:10:30 +01:00
if ( ! current_obj ) {
2021-05-04 16:00:45 +02:00
scene_tree_dock - > set_selected ( nullptr ) ;
get_inspector ( ) - > edit ( nullptr ) ;
node_dock - > set_node ( nullptr ) ;
inspector_dock - > update ( nullptr ) ;
2015-12-03 16:30:55 +01:00
2016-03-30 01:02:53 +02:00
_display_top_editors ( false ) ;
2015-12-03 16:30:55 +01:00
2014-02-10 02:10:30 +01:00
return ;
}
2020-01-24 18:08:27 +01:00
Object * prev_inspected_object = get_inspector ( ) - > get_edited_object ( ) ;
2018-06-14 20:36:38 +02:00
bool disable_folding = bool ( EDITOR_GET ( " interface/inspector/disable_folding " ) ) ;
2017-01-03 03:03:46 +01:00
bool is_resource = current_obj - > is_class ( " Resource " ) ;
bool is_node = current_obj - > is_class ( " Node " ) ;
2022-08-02 09:34:37 +02:00
bool stay_in_script_editor_on_node_selected = bool ( EDITOR_GET ( " text_editor/navigation/stay_in_script_editor_on_node_selected " ) ) ;
bool skip_main_plugin = false ;
2018-05-17 08:01:47 +02:00
String editable_warning ; //none by default
2018-11-27 22:56:31 +01:00
2015-09-01 05:49:47 +02:00
if ( is_resource ) {
2017-08-24 22:58:51 +02:00
Resource * current_res = Object : : cast_to < Resource > ( current_obj ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! current_res ) ;
2018-05-17 08:01:47 +02:00
get_inspector ( ) - > edit ( current_res ) ;
2021-05-04 16:00:45 +02:00
scene_tree_dock - > set_selected ( nullptr ) ;
node_dock - > set_node ( nullptr ) ;
inspector_dock - > update ( nullptr ) ;
2017-06-27 00:57:18 +02:00
EditorNode : : get_singleton ( ) - > get_import_dock ( ) - > set_edit_path ( current_res - > get_path ( ) ) ;
2017-09-14 15:38:59 +02:00
int subr_idx = current_res - > get_path ( ) . find ( " :: " ) ;
2017-09-15 00:38:38 +02:00
if ( subr_idx ! = - 1 ) {
String base_path = current_res - > get_path ( ) . substr ( 0 , subr_idx ) ;
if ( FileAccess : : exists ( base_path + " .import " ) ) {
editable_warning = TTR ( " This resource belongs to a scene that was imported, so it's not editable. \n Please read the documentation relevant to importing scenes to better understand this workflow. " ) ;
2017-09-14 15:38:59 +02:00
} else {
2017-12-05 17:25:52 +01:00
if ( ( ! get_edited_scene ( ) | | get_edited_scene ( ) - > get_filename ( ) ! = base_path ) & & ResourceLoader : : get_resource_type ( base_path ) = = " PackedScene " ) {
2019-03-25 01:54:29 +01:00
editable_warning = TTR ( " This resource belongs to a scene that was instanced or inherited. \n Changes to it won't be kept when saving the current scene. " ) ;
2017-09-14 15:38:59 +02:00
}
}
2017-09-15 00:38:38 +02:00
} else if ( current_res - > get_path ( ) . is_resource_file ( ) ) {
if ( FileAccess : : exists ( current_res - > get_path ( ) + " .import " ) ) {
2017-10-20 04:40:12 +02:00
editable_warning = TTR ( " This resource was imported, so it's not editable. Change its settings in the import panel and then re-import. " ) ;
2017-09-14 15:38:59 +02:00
}
}
2016-07-09 16:46:59 +02:00
} else if ( is_node ) {
2017-08-24 22:58:51 +02:00
Node * current_node = Object : : cast_to < Node > ( current_obj ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! current_node ) ;
2018-05-17 08:01:47 +02:00
get_inspector ( ) - > edit ( current_node ) ;
2017-05-29 02:46:48 +02:00
if ( current_node - > is_inside_tree ( ) ) {
node_dock - > set_node ( current_node ) ;
scene_tree_dock - > set_selected ( current_node ) ;
2019-07-25 05:10:31 +02:00
inspector_dock - > update ( current_node ) ;
2022-08-02 09:34:37 +02:00
if ( ! inspector_only & & ! skip_main_plugin ) {
skip_main_plugin = stay_in_script_editor_on_node_selected & & ScriptEditor : : get_singleton ( ) - > is_visible_in_tree ( ) ;
2022-07-23 14:29:30 +02:00
}
2017-05-29 02:46:48 +02:00
} else {
2021-05-04 16:00:45 +02:00
node_dock - > set_node ( nullptr ) ;
scene_tree_dock - > set_selected ( nullptr ) ;
inspector_dock - > update ( nullptr ) ;
2017-05-29 02:46:48 +02:00
}
2014-02-10 02:10:30 +01:00
2017-09-15 00:38:38 +02:00
if ( get_edited_scene ( ) & & get_edited_scene ( ) - > get_filename ( ) ! = String ( ) ) {
2017-09-14 15:38:59 +02:00
String source_scene = get_edited_scene ( ) - > get_filename ( ) ;
2017-09-15 00:38:38 +02:00
if ( FileAccess : : exists ( source_scene + " .import " ) ) {
2019-03-25 01:54:29 +01:00
editable_warning = TTR ( " This scene was imported, so changes to it won't be kept. \n Instancing it or inheriting will allow making changes to it. \n Please read the documentation relevant to importing scenes to better understand this workflow. " ) ;
2017-09-14 15:38:59 +02:00
}
}
2015-08-25 05:08:45 +02:00
} else {
2021-05-04 16:00:45 +02:00
Node * selected_node = nullptr ;
2019-11-10 09:37:51 +01:00
2017-10-17 16:39:31 +02:00
if ( current_obj - > is_class ( " ScriptEditorDebuggerInspectedObject " ) ) {
2019-03-25 01:54:29 +01:00
editable_warning = TTR ( " This is a remote object, so changes to it won't be kept. \n Please read the documentation relevant to debugging to better understand this workflow. " ) ;
2018-06-14 20:36:38 +02:00
disable_folding = true ;
2019-11-10 09:37:51 +01:00
} else if ( current_obj - > is_class ( " MultiNodeEdit " ) ) {
Node * scene = get_edited_scene ( ) ;
if ( scene ) {
MultiNodeEdit * multi_node_edit = Object : : cast_to < MultiNodeEdit > ( current_obj ) ;
int node_count = multi_node_edit - > get_node_count ( ) ;
if ( node_count > 0 ) {
List < Node * > multi_nodes ;
for ( int node_index = 0 ; node_index < node_count ; + + node_index ) {
Node * node = scene - > get_node ( multi_node_edit - > get_node ( node_index ) ) ;
if ( node ) {
multi_nodes . push_back ( node ) ;
}
}
if ( ! multi_nodes . empty ( ) ) {
// Pick the top-most node
multi_nodes . sort_custom < Node : : Comparator > ( ) ;
selected_node = multi_nodes . front ( ) - > get ( ) ;
}
}
}
2017-10-17 16:39:31 +02:00
}
2018-05-17 08:01:47 +02:00
get_inspector ( ) - > edit ( current_obj ) ;
2021-05-04 16:00:45 +02:00
node_dock - > set_node ( nullptr ) ;
2019-11-10 09:37:51 +01:00
scene_tree_dock - > set_selected ( selected_node ) ;
2021-05-04 16:00:45 +02:00
inspector_dock - > update ( nullptr ) ;
2014-02-10 02:10:30 +01:00
}
2020-01-24 18:08:27 +01:00
if ( current_obj = = prev_inspected_object ) {
// Make sure inspected properties are restored.
get_inspector ( ) - > update_tree ( ) ;
}
2018-05-17 08:01:47 +02:00
inspector_dock - > set_warning ( editable_warning ) ;
2017-09-14 15:38:59 +02:00
2018-06-14 20:36:38 +02:00
if ( get_inspector ( ) - > is_using_folding ( ) = = disable_folding ) {
get_inspector ( ) - > set_use_folding ( ! disable_folding ) ;
}
2014-02-10 02:10:30 +01:00
/* Take care of PLUGIN EDITOR */
2018-06-19 03:10:48 +02:00
if ( ! inspector_only ) {
EditorPlugin * main_plugin = editor_data . get_editor ( current_obj ) ;
2014-02-10 02:10:30 +01:00
2021-06-09 01:27:30 +02:00
int plugin_index = 0 ;
for ( ; plugin_index < editor_table . size ( ) ; plugin_index + + ) {
if ( editor_table [ plugin_index ] = = main_plugin ) {
if ( ! main_editor_buttons [ plugin_index ] - > is_visible ( ) ) {
main_plugin = nullptr ; //if button is not visible, then no plugin active
}
break ;
2019-04-09 00:18:03 +02:00
}
}
2022-08-02 09:34:37 +02:00
if ( main_plugin & & ! skip_main_plugin ) {
2018-06-19 03:10:48 +02:00
// special case if use of external editor is true
2021-09-12 21:17:34 +02:00
Resource * current_res = Object : : cast_to < Resource > ( current_obj ) ;
if ( main_plugin - > get_name ( ) = = " Script " & & current_obj - > get_class_name ( ) ! = StringName ( " VisualScript " ) & & current_res & & ! current_res - > get_path ( ) . empty ( ) & & current_res - > get_path ( ) . find ( " :: " ) = = - 1 & & ( bool ( EditorSettings : : get_singleton ( ) - > get ( " text_editor/external/use_external_editor " ) ) | | overrides_external_editor ( current_obj ) ) ) {
2021-05-05 12:44:11 +02:00
if ( ! changing_scene ) {
2018-06-19 03:10:48 +02:00
main_plugin - > edit ( current_obj ) ;
2021-05-05 12:44:11 +02:00
}
2018-06-19 03:10:48 +02:00
}
2014-02-10 02:10:30 +01:00
2018-06-19 03:10:48 +02:00
else if ( main_plugin ! = editor_plugin_screen & & ( ! ScriptEditor : : get_singleton ( ) | | ! ScriptEditor : : get_singleton ( ) - > is_visible_in_tree ( ) | | ScriptEditor : : get_singleton ( ) - > can_take_away_focus ( ) ) ) {
// update screen main_plugin
2021-06-09 01:27:30 +02:00
_editor_select ( plugin_index ) ;
main_plugin - > edit ( current_obj ) ;
2018-06-19 03:10:48 +02:00
} else {
editor_plugin_screen - > edit ( current_obj ) ;
}
2014-02-10 02:10:30 +01:00
}
2019-04-09 00:18:03 +02:00
Vector < EditorPlugin * > sub_plugins ;
if ( ! _is_class_editor_disabled_by_feature_profile ( current_obj - > get_class ( ) ) ) {
sub_plugins = editor_data . get_subeditors ( current_obj ) ;
}
2014-02-10 02:10:30 +01:00
2018-06-19 03:10:48 +02:00
if ( ! sub_plugins . empty ( ) ) {
_display_top_editors ( false ) ;
2014-02-10 02:10:30 +01:00
2018-06-19 03:10:48 +02:00
_set_top_editors ( sub_plugins ) ;
_set_editing_top_editors ( current_obj ) ;
_display_top_editors ( true ) ;
} else if ( ! editor_plugins_over - > get_plugins_list ( ) . empty ( ) ) {
2019-03-04 20:44:39 +01:00
hide_top_editors ( ) ;
2018-06-19 03:10:48 +02:00
}
2014-02-10 02:10:30 +01:00
}
2018-05-17 08:01:47 +02:00
inspector_dock - > update ( current_obj ) ;
inspector_dock - > update_keying ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _run ( bool p_current , const String & p_custom ) {
if ( editor_run . get_status ( ) = = EditorRun : : STATUS_PLAY ) {
2014-02-10 02:10:30 +01:00
play_button - > set_pressed ( ! _playing_edited ) ;
play_scene_button - > set_pressed ( _playing_edited ) ;
return ;
}
play_button - > set_pressed ( false ) ;
2017-03-05 16:44:50 +01:00
play_button - > set_icon ( gui_base - > get_icon ( " MainPlay " , " EditorIcons " ) ) ;
2014-02-10 02:10:30 +01:00
play_scene_button - > set_pressed ( false ) ;
2017-03-05 16:44:50 +01:00
play_scene_button - > set_icon ( gui_base - > get_icon ( " PlayScene " , " EditorIcons " ) ) ;
2016-02-17 20:51:56 +01:00
play_custom_scene_button - > set_pressed ( false ) ;
2017-03-05 16:44:50 +01:00
play_custom_scene_button - > set_icon ( gui_base - > get_icon ( " PlayCustom " , " EditorIcons " ) ) ;
2014-02-10 02:10:30 +01:00
String run_filename ;
String args ;
2019-07-29 20:09:22 +02:00
bool skip_breakpoints ;
2014-02-10 02:10:30 +01:00
2020-07-23 18:38:32 +02:00
if ( p_current | | ( editor_data . get_edited_scene_root ( ) & & p_custom ! = String ( ) & & p_custom = = editor_data . get_edited_scene_root ( ) - > get_filename ( ) ) ) {
2015-06-22 05:03:19 +02:00
Node * scene = editor_data . get_edited_scene_root ( ) ;
2014-02-10 02:10:30 +01:00
if ( ! scene ) {
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " There is no defined scene to run. " ) , TTR ( " OK " ) ) ;
2014-02-10 02:10:30 +01:00
return ;
}
2017-03-05 16:44:50 +01:00
if ( scene - > get_filename ( ) = = " " ) {
current_option = - 1 ;
2021-01-06 02:17:56 +01:00
_menu_option ( FILE_SAVE_AS_SCENE ) ;
// Set the option to save and run so when the dialog is accepted, the scene runs.
current_option = FILE_SAVE_AND_RUN ;
file - > set_title ( TTR ( " Save scene before running... " ) ) ;
2014-02-10 02:10:30 +01:00
return ;
}
2017-03-05 16:44:50 +01:00
run_filename = scene - > get_filename ( ) ;
} else if ( p_custom ! = " " ) {
2017-02-27 15:20:47 +01:00
run_filename = p_custom ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
if ( run_filename = = " " ) {
2014-02-10 02:10:30 +01:00
//evidently, run the scene
2019-03-22 02:08:28 +01:00
if ( ! ensure_main_scene ( false ) ) {
2016-06-27 15:59:37 +02:00
return ;
}
2014-02-10 02:10:30 +01:00
}
2018-05-17 23:02:16 +02:00
if ( bool ( EDITOR_GET ( " run/auto_save/save_before_running " ) ) ) {
2014-02-10 02:10:30 +01:00
if ( unsaved_cache ) {
2015-06-22 05:03:19 +02:00
Node * scene = editor_data . get_edited_scene_root ( ) ;
2014-02-10 02:10:30 +01:00
2020-07-23 18:38:32 +02:00
if ( scene & & scene - > get_filename ( ) ! = " " ) { // Only autosave if there is a scene and if it has a path.
2015-05-31 06:59:42 +02:00
_save_scene_with_preview ( scene - > get_filename ( ) ) ;
2014-02-10 02:10:30 +01:00
}
}
2016-06-26 05:54:17 +02:00
_menu_option ( FILE_SAVE_ALL_SCENES ) ;
2014-02-10 02:10:30 +01:00
editor_data . save_editor_external_data ( ) ;
}
2021-05-05 12:44:11 +02:00
if ( ! call_build ( ) ) {
2017-08-29 23:59:20 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-08-29 23:59:20 +02:00
2018-05-17 23:02:16 +02:00
if ( bool ( EDITOR_GET ( " run/output/always_clear_output_on_play " ) ) ) {
2015-07-30 00:03:25 +02:00
log - > clear ( ) ;
}
2018-05-17 23:02:16 +02:00
if ( bool ( EDITOR_GET ( " run/output/always_open_output_on_play " ) ) ) {
2016-12-24 23:39:16 +01:00
make_bottom_panel_item_visible ( log ) ;
}
2014-02-10 02:10:30 +01:00
List < String > breakpoints ;
editor_data . get_editor_breakpoints ( & breakpoints ) ;
2017-01-21 23:00:25 +01:00
2017-07-19 22:00:46 +02:00
args = ProjectSettings : : get_singleton ( ) - > get ( " editor/main_run_args " ) ;
2019-07-29 20:09:22 +02:00
skip_breakpoints = ScriptEditor : : get_singleton ( ) - > get_debugger ( ) - > is_skip_breakpoints ( ) ;
2020-03-15 11:45:39 +01:00
emit_signal ( " play_pressed " ) ;
2014-02-10 02:10:30 +01:00
2019-07-29 20:09:22 +02:00
Error error = editor_run . run ( run_filename , args , breakpoints , skip_breakpoints ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( error ! = OK ) {
2020-03-15 11:45:39 +01:00
emit_signal ( " stop_pressed " ) ;
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " Could not start subprocess! " ) , TTR ( " OK " ) ) ;
2014-02-10 02:10:30 +01:00
return ;
}
if ( p_current ) {
play_scene_button - > set_pressed ( true ) ;
2017-03-05 16:44:50 +01:00
play_scene_button - > set_icon ( gui_base - > get_icon ( " Reload " , " EditorIcons " ) ) ;
} else if ( p_custom ! = " " ) {
run_custom_filename = p_custom ;
2016-02-17 20:51:56 +01:00
play_custom_scene_button - > set_pressed ( true ) ;
2017-03-05 16:44:50 +01:00
play_custom_scene_button - > set_icon ( gui_base - > get_icon ( " Reload " , " EditorIcons " ) ) ;
2014-02-10 02:10:30 +01:00
} else {
play_button - > set_pressed ( true ) ;
2017-03-05 16:44:50 +01:00
play_button - > set_icon ( gui_base - > get_icon ( " Reload " , " EditorIcons " ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-12-04 20:48:46 +01:00
stop_button - > set_disabled ( false ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
_playing_edited = p_current ;
2014-02-10 02:10:30 +01:00
}
2021-07-15 15:12:56 +02:00
void EditorNode : : _android_build_source_selected ( const String & p_file ) {
export_template_manager - > install_android_template_from_file ( p_file ) ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _menu_option_confirm ( int p_option , bool p_confirmed ) {
2021-05-05 12:44:11 +02:00
if ( ! p_confirmed ) { //this may be a hack..
2017-03-05 16:44:50 +01:00
current_option = ( MenuOptions ) p_option ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
switch ( p_option ) {
2014-02-10 02:10:30 +01:00
case FILE_NEW_SCENE : {
2019-08-15 19:47:21 +02:00
new_scene ( ) ;
2014-02-10 02:10:30 +01:00
} break ;
2015-10-10 14:09:09 +02:00
case FILE_NEW_INHERITED_SCENE :
2014-02-10 02:10:30 +01:00
case FILE_OPEN_SCENE : {
2015-05-31 06:59:42 +02:00
file - > set_mode ( EditorFileDialog : : MODE_OPEN_FILE ) ;
2014-02-10 02:10:30 +01:00
List < String > extensions ;
2017-03-05 16:44:50 +01:00
ResourceLoader : : get_recognized_extensions_for_type ( " PackedScene " , & extensions ) ;
2014-02-10 02:10:30 +01:00
file - > clear_filters ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < extensions . size ( ) ; i + + ) {
file - > add_filter ( " *. " + extensions [ i ] + " ; " + extensions [ i ] . to_upper ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2016-03-09 00:00:52 +01:00
2015-06-22 05:03:19 +02:00
Node * scene = editor_data . get_edited_scene_root ( ) ;
2014-02-10 02:10:30 +01:00
if ( scene ) {
file - > set_current_path ( scene - > get_filename ( ) ) ;
} ;
2017-03-05 16:44:50 +01:00
file - > set_title ( p_option = = FILE_OPEN_SCENE ? TTR ( " Open Scene " ) : TTR ( " Open Base Scene " ) ) ;
2014-02-10 02:10:30 +01:00
file - > popup_centered_ratio ( ) ;
2016-03-09 00:00:52 +01:00
2019-05-09 22:06:35 +02:00
} break ;
case FILE_QUICK_OPEN : {
quick_open - > popup_dialog ( " Resource " , true ) ;
quick_open - > set_title ( TTR ( " Quick Open... " ) ) ;
2014-02-10 02:10:30 +01:00
} break ;
case FILE_QUICK_OPEN_SCENE : {
2018-10-02 12:07:44 +02:00
quick_open - > popup_dialog ( " PackedScene " , true ) ;
2018-04-22 19:36:01 +02:00
quick_open - > set_title ( TTR ( " Quick Open Scene... " ) ) ;
2014-02-10 02:10:30 +01:00
} break ;
case FILE_QUICK_OPEN_SCRIPT : {
2018-10-02 12:07:44 +02:00
quick_open - > popup_dialog ( " Script " , true ) ;
2018-04-22 19:36:01 +02:00
quick_open - > set_title ( TTR ( " Quick Open Script... " ) ) ;
2014-02-10 02:10:30 +01:00
} break ;
case FILE_OPEN_PREV : {
2021-05-05 12:44:11 +02:00
if ( previous_scenes . empty ( ) ) {
2014-02-10 02:10:30 +01:00
break ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
opening_prev = true ;
2014-02-10 02:10:30 +01:00
open_request ( previous_scenes . back ( ) - > get ( ) ) ;
2019-04-10 17:21:26 +02:00
previous_scenes . pop_back ( ) ;
2014-02-10 02:10:30 +01:00
2019-04-21 11:44:21 +02:00
} break ;
case FILE_CLOSE_OTHERS :
case FILE_CLOSE_RIGHT :
case FILE_CLOSE_ALL : {
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 ) ) {
int next_tab = editor_data . get_edited_scene ( ) + 1 ;
next_tab % = editor_data . get_edited_scene_count ( ) ;
_scene_tab_closed ( next_tab , current_option ) ;
} else {
2021-05-05 12:44:11 +02:00
if ( current_option ! = FILE_CLOSE_ALL ) {
2019-04-21 11:44:21 +02:00
current_option = - 1 ;
2021-05-05 12:44:11 +02:00
} else {
2019-04-21 11:44:21 +02:00
_scene_tab_closed ( editor_data . get_edited_scene ( ) ) ;
2021-05-05 12:44:11 +02:00
}
2019-04-21 11:44:21 +02:00
}
2021-05-05 12:44:11 +02:00
if ( p_confirmed ) {
2019-05-17 23:47:02 +02:00
_menu_option_confirm ( SCENE_TAB_CLOSE , true ) ;
2021-05-05 12:44:11 +02:00
}
2019-05-17 23:47:02 +02:00
2015-06-22 05:03:19 +02:00
} break ;
2017-06-26 16:04:53 +02:00
case FILE_CLOSE_ALL_AND_QUIT :
case FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER :
2022-03-23 12:07:29 +01:00
case FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT :
2015-06-22 05:03:19 +02:00
case FILE_CLOSE : {
2019-12-06 14:46:01 +01:00
if ( ! p_confirmed ) {
2017-07-26 13:29:45 +02:00
tab_closing = p_option = = FILE_CLOSE ? editor_data . get_edited_scene ( ) : _next_unsaved_scene ( false ) ;
2020-02-19 10:36:26 +01:00
_scene_tab_changed ( tab_closing ) ;
2019-12-06 14:46:01 +01:00
2022-03-23 12:07:29 +01:00
if ( unsaved_cache | | p_option = = FILE_CLOSE_ALL_AND_QUIT | | p_option = = FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER | | p_option = = FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT ) {
2021-03-13 18:19:29 +01:00
Node * scene_root = editor_data . get_edited_scene_root ( tab_closing ) ;
if ( scene_root ) {
String scene_filename = scene_root - > get_filename ( ) ;
2022-03-23 12:07:29 +01:00
if ( p_option = = FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT ) {
save_confirmation - > get_ok ( ) - > set_text ( TTR ( " Save & Reload " ) ) ;
save_confirmation - > set_text ( vformat ( TTR ( " Save changes to '%s' before reloading? " ) , scene_filename ! = " " ? scene_filename : " unsaved scene " ) ) ;
} else {
save_confirmation - > get_ok ( ) - > set_text ( TTR ( " Save & Close " ) ) ;
save_confirmation - > set_text ( vformat ( TTR ( " Save changes to '%s' before closing? " ) , scene_filename ! = " " ? scene_filename : " unsaved scene " ) ) ;
}
2021-03-13 18:19:29 +01:00
save_confirmation - > popup_centered_minsize ( ) ;
break ;
}
2019-12-06 14:46:01 +01:00
}
} else if ( p_option = = FILE_CLOSE ) {
2017-12-10 13:48:03 +01:00
tab_closing = editor_data . get_edited_scene ( ) ;
2015-06-22 05:03:19 +02:00
}
2018-01-02 08:10:49 +01:00
if ( ! editor_data . get_edited_scene_root ( tab_closing ) ) {
// empty tab
_scene_tab_closed ( tab_closing ) ;
break ;
}
2017-12-10 13:48:03 +01:00
2019-04-05 14:06:16 +02:00
FALLTHROUGH ;
}
2017-06-21 06:15:39 +02:00
case SCENE_TAB_CLOSE :
2014-02-10 02:10:30 +01:00
case FILE_SAVE_SCENE : {
2017-06-26 16:04:53 +02:00
int scene_idx = ( p_option = = FILE_SAVE_SCENE ) ? - 1 : tab_closing ;
2017-06-21 06:15:39 +02:00
Node * scene = editor_data . get_edited_scene_root ( scene_idx ) ;
2021-01-15 18:33:12 +01:00
if ( scene & & scene - > get_filename ( ) ! = " " ) {
2021-09-11 03:35:13 +02:00
if ( DirAccess : : exists ( scene - > get_filename ( ) . get_base_dir ( ) ) ) {
if ( scene_idx ! = editor_data . get_edited_scene ( ) ) {
_save_scene_with_preview ( scene - > get_filename ( ) , scene_idx ) ;
} else {
_save_scene_with_preview ( scene - > get_filename ( ) ) ;
}
2017-06-21 06:15:39 +02:00
2021-09-11 03:35:13 +02:00
if ( scene_idx ! = - 1 ) {
_discard_changes ( ) ;
}
save_layout ( ) ;
} else {
show_save_accept ( vformat ( TTR ( " %s no longer exists! Please specify a new save location. " ) , scene - > get_filename ( ) . get_base_dir ( ) ) , TTR ( " OK " ) ) ;
2021-05-05 12:44:11 +02:00
}
2017-06-26 16:04:53 +02:00
break ;
}
2019-04-05 14:06:16 +02:00
FALLTHROUGH ;
}
2014-02-10 02:10:30 +01:00
case FILE_SAVE_AS_SCENE : {
2017-06-26 16:04:53 +02:00
int scene_idx = ( p_option = = FILE_SAVE_SCENE | | p_option = = FILE_SAVE_AS_SCENE ) ? - 1 : tab_closing ;
2016-03-09 00:00:52 +01:00
2017-06-26 16:04:53 +02:00
Node * scene = editor_data . get_edited_scene_root ( scene_idx ) ;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
if ( ! scene ) {
2021-05-09 12:29:50 +02:00
if ( p_option = = FILE_SAVE_SCENE ) {
// Pressing Ctrl + S saves the current script if a scene is currently open, but it won't if the scene has no root node.
// Work around this by explicitly saving the script in this case (similar to pressing Ctrl + Alt + S).
ScriptEditor : : get_singleton ( ) - > save_current_script ( ) ;
}
const int saved = _save_external_resources ( ) ;
2019-02-28 00:00:40 +01:00
if ( saved > 0 ) {
2021-05-09 12:29:50 +02:00
show_accept (
vformat ( TTR ( " The current scene has no root node, but %d modified external resource(s) were saved anyway. " ) , saved ) ,
TTR ( " OK " ) ) ;
} else if ( p_option = = FILE_SAVE_AS_SCENE ) {
// Don't show this dialog when pressing Ctrl + S to avoid interfering with script saving.
show_accept (
TTR ( " A root node is required to save the scene. You can add a root node using the Scene tree dock. " ) ,
TTR ( " OK " ) ) ;
2019-02-28 00:00:40 +01:00
}
2016-03-09 00:00:52 +01:00
break ;
2014-02-10 02:10:30 +01:00
}
2016-03-09 00:00:52 +01:00
2015-05-31 06:59:42 +02:00
file - > set_mode ( EditorFileDialog : : MODE_SAVE_FILE ) ;
2014-02-10 02:10:30 +01:00
List < String > extensions ;
2017-03-05 16:44:50 +01:00
Ref < PackedScene > sd = memnew ( PackedScene ) ;
ResourceSaver : : get_recognized_extensions ( sd , & extensions ) ;
2014-02-10 02:10:30 +01:00
file - > clear_filters ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < extensions . size ( ) ; i + + ) {
file - > add_filter ( " *. " + extensions [ i ] + " ; " + extensions [ i ] . to_upper ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
if ( scene - > get_filename ( ) ! = " " ) {
2020-10-13 20:28:45 +02:00
String path = scene - > get_filename ( ) ;
file - > set_current_path ( path ) ;
2014-02-10 02:10:30 +01:00
if ( extensions . size ( ) ) {
2020-10-13 20:28:45 +02:00
String ext = path . get_extension ( ) . to_lower ( ) ;
2021-05-04 16:00:45 +02:00
if ( extensions . find ( ext ) = = nullptr ) {
2020-10-13 20:28:45 +02:00
file - > set_current_path ( path . replacen ( " . " + ext , " . " + extensions . front ( ) - > get ( ) ) ) ;
2014-02-10 02:10:30 +01:00
}
}
2022-01-18 17:12:39 +01:00
} else if ( extensions . size ( ) ) {
String root_name = scene - > get_name ( ) ;
// Very similar to node naming logic.
2022-06-19 11:42:54 +02:00
switch ( ProjectSettings : : get_singleton ( ) - > get ( " editor/scene_naming " ) . operator int ( ) ) {
2022-01-18 17:12:39 +01:00
case SCENE_NAME_CASING_AUTO :
// Use casing of the root node.
break ;
case SCENE_NAME_CASING_PASCAL_CASE : {
root_name = root_name . capitalize ( ) . replace ( " " , " " ) ;
} break ;
case SCENE_NAME_CASING_SNAKE_CASE :
root_name = root_name . capitalize ( ) . replace ( " " , " " ) . replace ( " - " , " _ " ) . camelcase_to_underscore ( ) ;
break ;
2014-02-10 02:10:30 +01:00
}
2022-01-18 17:12:39 +01:00
file - > set_current_path ( root_name + " . " + extensions . front ( ) - > get ( ) . to_lower ( ) ) ;
2014-02-10 02:10:30 +01:00
}
file - > popup_centered_ratio ( ) ;
2018-04-22 19:36:01 +02:00
file - > set_title ( TTR ( " Save Scene As... " ) ) ;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
} break ;
2016-06-26 05:54:17 +02:00
case FILE_SAVE_ALL_SCENES : {
2017-06-24 12:57:30 +02:00
_save_all_scenes ( ) ;
2016-06-26 05:54:17 +02:00
} break ;
2015-01-06 23:28:25 +01:00
2014-02-10 02:10:30 +01:00
case FILE_EXPORT_PROJECT : {
2017-02-20 03:19:30 +01:00
project_export - > popup_export ( ) ;
2014-02-10 02:10:30 +01:00
} break ;
case FILE_EXPORT_MESH_LIBRARY : {
2015-06-22 05:03:19 +02:00
if ( ! editor_data . get_edited_scene_root ( ) ) {
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " This operation can't be done without a scene. " ) , TTR ( " OK " ) ) ;
2014-02-10 02:10:30 +01:00
break ;
}
List < String > extensions ;
2017-03-05 16:44:50 +01:00
Ref < MeshLibrary > ml ( memnew ( MeshLibrary ) ) ;
ResourceSaver : : get_recognized_extensions ( ml , & extensions ) ;
2014-02-10 02:10:30 +01:00
file_export_lib - > clear_filters ( ) ;
2017-03-05 16:44:50 +01:00
for ( List < String > : : Element * E = extensions . front ( ) ; E ; E = E - > next ( ) ) {
file_export_lib - > add_filter ( " *. " + E - > get ( ) ) ;
2014-02-10 02:10:30 +01:00
}
file_export_lib - > popup_centered_ratio ( ) ;
2016-05-04 03:25:37 +02:00
file_export_lib - > set_title ( TTR ( " Export Mesh Library " ) ) ;
2014-02-10 02:10:30 +01:00
} break ;
case FILE_EXPORT_TILESET : {
2017-11-07 23:44:46 +01:00
//Make sure that the scene has a root before trying to convert to tileset
if ( ! editor_data . get_edited_scene_root ( ) ) {
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " This operation can't be done without a root node. " ) , TTR ( " OK " ) ) ;
2017-11-07 23:44:46 +01:00
break ;
}
2014-02-10 02:10:30 +01:00
List < String > extensions ;
2017-03-05 16:44:50 +01:00
Ref < TileSet > ml ( memnew ( TileSet ) ) ;
ResourceSaver : : get_recognized_extensions ( ml , & extensions ) ;
2014-02-10 02:10:30 +01:00
file_export_lib - > clear_filters ( ) ;
2017-03-05 16:44:50 +01:00
for ( List < String > : : Element * E = extensions . front ( ) ; E ; E = E - > next ( ) ) {
file_export_lib - > add_filter ( " *. " + E - > get ( ) ) ;
2014-02-10 02:10:30 +01:00
}
file_export_lib - > popup_centered_ratio ( ) ;
2016-05-04 03:25:37 +02:00
file_export_lib - > set_title ( TTR ( " Export Tile Set " ) ) ;
2014-02-10 02:10:30 +01:00
} break ;
case FILE_IMPORT_SUBSCENE : {
2015-06-22 05:03:19 +02:00
if ( ! editor_data . get_edited_scene_root ( ) ) {
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " This operation can't be done without a selected node. " ) , TTR ( " OK " ) ) ;
2014-02-10 02:10:30 +01:00
break ;
}
scene_tree_dock - > import_subscene ( ) ;
} break ;
case FILE_EXTERNAL_OPEN_SCENE : {
if ( unsaved_cache & & ! p_confirmed ) {
2016-05-04 03:25:37 +02:00
confirmation - > get_ok ( ) - > set_text ( TTR ( " Open " ) ) ;
confirmation - > set_text ( TTR ( " Current scene not saved. Open anyway? " ) ) ;
2015-04-08 19:02:13 +02:00
confirmation - > popup_centered_minsize ( ) ;
2014-02-10 02:10:30 +01:00
break ;
}
2017-03-05 16:44:50 +01:00
bool oprev = opening_prev ;
2014-02-10 02:10:30 +01:00
Error err = load_scene ( external_file ) ;
if ( err = = OK & & oprev ) {
previous_scenes . pop_back ( ) ;
2017-03-05 16:44:50 +01:00
opening_prev = false ;
2014-02-10 02:10:30 +01:00
}
} break ;
case EDIT_UNDO : {
2017-03-05 16:44:50 +01:00
if ( Input : : get_singleton ( ) - > get_mouse_button_mask ( ) & 0x7 ) {
2021-08-17 05:41:49 +02:00
log - > add_message ( TTR ( " Can't undo while mouse buttons are pressed. " ) , EditorLog : : MSG_TYPE_EDITOR ) ;
2018-05-27 04:41:19 +02:00
} else {
String action = editor_data . get_undo_redo ( ) . get_current_action_name ( ) ;
2014-02-10 02:10:30 +01:00
2018-05-27 04:41:19 +02:00
if ( ! editor_data . get_undo_redo ( ) . undo ( ) ) {
2021-08-17 05:41:49 +02:00
log - > add_message ( TTR ( " Nothing to undo. " ) , EditorLog : : MSG_TYPE_EDITOR ) ;
2018-05-27 04:41:19 +02:00
} else if ( action ! = " " ) {
2021-08-17 05:41:49 +02:00
log - > add_message ( vformat ( TTR ( " Undo: %s " ) , action ) , EditorLog : : MSG_TYPE_EDITOR ) ;
2018-05-27 04:41:19 +02:00
}
}
2014-02-10 02:10:30 +01:00
} break ;
case EDIT_REDO : {
2018-05-27 04:41:19 +02:00
if ( Input : : get_singleton ( ) - > get_mouse_button_mask ( ) & 0x7 ) {
2021-08-17 05:41:49 +02:00
log - > add_message ( TTR ( " Can't redo while mouse buttons are pressed. " ) , EditorLog : : MSG_TYPE_EDITOR ) ;
2018-05-27 04:41:19 +02:00
} else {
if ( ! editor_data . get_undo_redo ( ) . redo ( ) ) {
2021-08-17 05:41:49 +02:00
log - > add_message ( TTR ( " Nothing to redo. " ) , EditorLog : : MSG_TYPE_EDITOR ) ;
2018-05-27 04:41:19 +02:00
} else {
String action = editor_data . get_undo_redo ( ) . get_current_action_name ( ) ;
2021-08-17 05:41:49 +02:00
log - > add_message ( vformat ( TTR ( " Redo: %s " ) , action ) , EditorLog : : MSG_TYPE_EDITOR ) ;
2018-05-27 04:41:19 +02:00
}
}
2014-02-10 02:10:30 +01:00
} break ;
2015-01-25 01:14:06 +01:00
2020-05-10 20:12:25 +02:00
case EDIT_RELOAD_SAVED_SCENE : {
2015-01-25 01:14:06 +01:00
Node * scene = get_edited_scene ( ) ;
2021-05-05 12:44:11 +02:00
if ( ! scene ) {
2015-01-25 01:14:06 +01:00
break ;
2021-05-05 12:44:11 +02:00
}
2016-01-23 22:28:30 +01:00
String filename = scene - > get_filename ( ) ;
2017-03-05 16:44:50 +01:00
if ( filename = = String ( ) ) {
2016-05-19 00:08:12 +02:00
show_warning ( TTR ( " Can't reload a scene that was never saved. " ) ) ;
2016-01-23 22:28:30 +01:00
break ;
}
2015-01-27 01:00:07 +01:00
if ( unsaved_cache & & ! p_confirmed ) {
2020-05-10 20:12:25 +02:00
confirmation - > get_ok ( ) - > set_text ( TTR ( " Reload Saved Scene " ) ) ;
confirmation - > set_text (
TTR ( " The current scene has unsaved changes. \n Reload the saved scene anyway? This action cannot be undone. " ) ) ;
2015-04-08 19:02:13 +02:00
confirmation - > popup_centered_minsize ( ) ;
2015-01-27 01:00:07 +01:00
break ;
}
2015-01-25 01:14:06 +01:00
2016-01-23 22:28:30 +01:00
int cur_idx = editor_data . get_edited_scene ( ) ;
_remove_edited_scene ( ) ;
Error err = load_scene ( filename ) ;
2017-09-02 22:32:31 +02:00
if ( err ! = OK )
ERR_PRINT ( " Failed to load scene " ) ;
2016-01-23 22:28:30 +01:00
editor_data . move_edited_scene_to_index ( cur_idx ) ;
2018-11-18 21:07:38 +01:00
get_undo_redo ( ) - > clear_history ( false ) ;
2016-01-23 22:28:30 +01:00
scene_tabs - > set_current_tab ( cur_idx ) ;
2015-01-25 01:14:06 +01:00
2014-11-02 15:31:01 +01:00
} break ;
2014-02-10 02:10:30 +01:00
case RUN_PLAY : {
2020-04-05 16:19:24 +02:00
run_play ( ) ;
2014-02-10 02:10:30 +01:00
} break ;
case RUN_PLAY_CUSTOM_SCENE : {
2017-03-05 16:44:50 +01:00
if ( run_custom_filename . empty ( ) | | editor_run . get_status ( ) = = EditorRun : : STATUS_STOP ) {
_menu_option_confirm ( RUN_STOP , true ) ;
2018-10-02 12:07:44 +02:00
quick_run - > popup_dialog ( " PackedScene " , true ) ;
2018-04-22 19:36:01 +02:00
quick_run - > set_title ( TTR ( " Quick Run Scene... " ) ) ;
2016-02-18 13:16:31 +01:00
play_custom_scene_button - > set_pressed ( false ) ;
2016-02-17 20:51:56 +01:00
} else {
2017-03-05 16:44:50 +01:00
String last_custom_scene = run_custom_filename ;
2020-04-05 16:19:24 +02:00
run_play_custom ( last_custom_scene ) ;
2016-02-17 20:51:56 +01:00
}
2014-02-10 02:10:30 +01:00
} break ;
case RUN_STOP : {
2021-05-05 12:44:11 +02:00
if ( editor_run . get_status ( ) = = EditorRun : : STATUS_STOP ) {
2014-02-10 02:10:30 +01:00
break ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
editor_run . stop ( ) ;
2016-02-17 20:51:56 +01:00
run_custom_filename . clear ( ) ;
2014-02-10 02:10:30 +01:00
play_button - > set_pressed ( false ) ;
2017-03-05 16:44:50 +01:00
play_button - > set_icon ( gui_base - > get_icon ( " MainPlay " , " EditorIcons " ) ) ;
2014-02-10 02:10:30 +01:00
play_scene_button - > set_pressed ( false ) ;
2017-03-05 16:44:50 +01:00
play_scene_button - > set_icon ( gui_base - > get_icon ( " PlayScene " , " EditorIcons " ) ) ;
2016-02-17 20:51:56 +01:00
play_custom_scene_button - > set_pressed ( false ) ;
2017-03-05 16:44:50 +01:00
play_custom_scene_button - > set_icon ( gui_base - > get_icon ( " PlayCustom " , " EditorIcons " ) ) ;
2017-12-04 20:48:46 +01:00
stop_button - > set_disabled ( true ) ;
2018-05-17 23:02:16 +02:00
if ( bool ( EDITOR_GET ( " run/output/always_close_output_on_stop " ) ) ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < bottom_panel_items . size ( ) ; i + + ) {
if ( bottom_panel_items [ i ] . control = = log ) {
_bottom_panel_switch ( false , i ) ;
2017-02-06 17:50:01 +01:00
break ;
}
}
}
2014-02-10 02:10:30 +01:00
emit_signal ( " stop_pressed " ) ;
} break ;
2018-09-13 19:06:40 +02:00
case FILE_SHOW_IN_FILESYSTEM : {
String path = editor_data . get_scene_path ( editor_data . get_edited_scene ( ) ) ;
if ( path ! = String ( ) ) {
filesystem_dock - > navigate_to_path ( path ) ;
}
} break ;
2014-02-10 02:10:30 +01:00
case RUN_PLAY_SCENE : {
2020-04-05 16:19:24 +02:00
run_play_current ( ) ;
2014-02-10 02:10:30 +01:00
2015-08-06 07:37:40 +02:00
} break ;
case RUN_PLAY_NATIVE : {
2018-05-17 23:02:16 +02:00
bool autosave = EDITOR_GET ( " run/auto_save/save_before_running " ) ;
2016-06-24 14:20:43 +02:00
if ( autosave ) {
2016-07-10 19:37:48 +02:00
_menu_option_confirm ( FILE_SAVE_ALL_SCENES , false ) ;
2016-06-24 14:20:43 +02:00
}
2017-03-05 16:44:50 +01:00
if ( run_native - > is_deploy_debug_remote_enabled ( ) ) {
_menu_option_confirm ( RUN_STOP , true ) ;
2017-08-29 23:59:20 +02:00
2021-05-05 12:44:11 +02:00
if ( ! call_build ( ) ) {
2017-08-29 23:59:20 +02:00
break ; // build failed
2021-05-05 12:44:11 +02:00
}
2017-08-29 23:59:20 +02:00
2016-06-24 14:20:43 +02:00
emit_signal ( " play_pressed " ) ;
editor_run . run_native_notify ( ) ;
}
2014-02-10 02:10:30 +01:00
} break ;
case RUN_SCENE_SETTINGS : {
run_settings_dialog - > popup_run_settings ( ) ;
} break ;
case RUN_SETTINGS : {
project_settings - > popup_project_settings ( ) ;
} break ;
2019-04-07 20:46:52 +02:00
case FILE_INSTALL_ANDROID_SOURCE : {
if ( p_confirmed ) {
export_template_manager - > install_android_template ( ) ;
} else {
if ( DirAccess : : exists ( " res://android/build " ) ) {
remove_android_build_template - > popup_centered_minsize ( ) ;
} else if ( export_template_manager - > can_install_android_template ( ) ) {
install_android_build_template - > popup_centered_minsize ( ) ;
} else {
custom_build_manage_templates - > popup_centered_minsize ( ) ;
}
}
} break ;
2021-12-28 01:51:45 +01:00
case RUN_USER_DATA_FOLDER : {
// ensure_user_data_dir() to prevent the edge case: "Open User Data Folder" won't work after the project was renamed in ProjectSettingsEditor unless the project is saved
2020-09-13 14:49:53 +02:00
OS : : get_singleton ( ) - > ensure_user_data_dir ( ) ;
2019-09-04 19:46:12 +02:00
OS : : get_singleton ( ) - > shell_open ( String ( " file:// " ) + OS : : get_singleton ( ) - > get_user_data_dir ( ) ) ;
} break ;
2019-04-07 20:46:52 +02:00
case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES : {
2019-06-16 14:12:01 +02:00
OS : : get_singleton ( ) - > shell_open ( " file:// " + ProjectSettings : : get_singleton ( ) - > get_resource_path ( ) . plus_file ( " android " ) ) ;
2019-04-07 20:46:52 +02:00
} break ;
2017-06-26 16:04:53 +02:00
case FILE_QUIT :
2022-03-23 12:07:29 +01:00
case RUN_PROJECT_MANAGER :
case RELOAD_CURRENT_PROJECT : {
2014-02-18 05:21:06 +01:00
if ( ! p_confirmed ) {
2018-05-17 23:02:16 +02:00
bool save_each = EDITOR_GET ( " interface/editor/save_each_scene_on_quit " ) ;
2017-07-26 13:29:45 +02:00
if ( _next_unsaved_scene ( ! save_each ) = = - 1 ) {
2022-05-05 21:01:11 +02:00
bool confirm = ( p_option ! = RELOAD_CURRENT_PROJECT ) & & EDITOR_GET ( " interface/editor/quit_confirmation " ) ;
2017-06-26 16:04:53 +02:00
if ( confirm ) {
confirmation - > get_ok ( ) - > set_text ( p_option = = FILE_QUIT ? TTR ( " Quit " ) : TTR ( " Yes " ) ) ;
confirmation - > set_text ( p_option = = FILE_QUIT ? TTR ( " Exit the editor? " ) : TTR ( " Open Project Manager? " ) ) ;
confirmation - > popup_centered_minsize ( ) ;
} else {
_discard_changes ( ) ;
2017-06-29 20:39:26 +02:00
break ;
2017-06-26 16:04:53 +02:00
}
2017-06-24 12:57:30 +02:00
} else {
2017-06-26 16:04:53 +02:00
if ( save_each ) {
2022-03-23 12:07:29 +01:00
if ( p_option = = RELOAD_CURRENT_PROJECT ) {
_menu_option_confirm ( FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT , false ) ;
} else if ( p_option = = FILE_QUIT ) {
_menu_option_confirm ( FILE_CLOSE_ALL_AND_QUIT , false ) ;
} else {
_menu_option_confirm ( FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER , false ) ;
}
2017-06-26 16:04:53 +02:00
} else {
String unsaved_scenes ;
2017-07-26 13:29:45 +02:00
int i = _next_unsaved_scene ( true , 0 ) ;
while ( i ! = - 1 ) {
unsaved_scenes + = " \n " + editor_data . get_edited_scene_root ( i ) - > get_filename ( ) ;
i = _next_unsaved_scene ( true , + + i ) ;
2017-06-26 16:04:53 +02:00
}
2022-03-23 12:07:29 +01:00
if ( p_option = = RELOAD_CURRENT_PROJECT ) {
save_confirmation - > get_ok ( ) - > set_text ( TTR ( " Save & Reload " ) ) ;
save_confirmation - > set_text ( TTR ( " Save changes to the following scene(s) before reloading? " ) + unsaved_scenes ) ;
} else {
save_confirmation - > get_ok ( ) - > set_text ( TTR ( " Save & Quit " ) ) ;
save_confirmation - > set_text ( ( p_option = = FILE_QUIT ? TTR ( " Save changes to the following scene(s) before quitting? " ) : TTR ( " Save changes to the following scene(s) before opening Project Manager? " ) ) + unsaved_scenes ) ;
}
2017-06-26 16:04:53 +02:00
save_confirmation - > popup_centered_minsize ( ) ;
}
2017-06-24 12:57:30 +02:00
}
2017-06-26 16:04:53 +02:00
2017-07-23 09:36:38 +02:00
OS : : get_singleton ( ) - > request_attention ( ) ;
2017-06-26 16:04:53 +02:00
break ;
2017-06-24 12:57:30 +02:00
}
2014-02-18 05:21:06 +01:00
2017-07-26 13:29:45 +02:00
if ( _next_unsaved_scene ( true ) ! = - 1 ) {
2017-06-24 12:57:30 +02:00
_save_all_scenes ( ) ;
2017-06-26 16:04:53 +02:00
}
2017-06-24 12:57:30 +02:00
_discard_changes ( ) ;
2014-02-18 05:21:06 +01:00
} break ;
2014-02-10 02:10:30 +01:00
case RUN_FILE_SERVER : {
2017-05-24 12:00:55 +02:00
bool ischecked = debug_menu - > get_popup ( ) - > is_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_FILE_SERVER ) ) ;
2014-02-10 02:10:30 +01:00
if ( ischecked ) {
file_server - > stop ( ) ;
2016-06-03 17:34:11 +02:00
run_native - > set_deploy_dumb ( false ) ;
2014-02-10 02:10:30 +01:00
} else {
file_server - > start ( ) ;
2016-06-03 17:34:11 +02:00
run_native - > set_deploy_dumb ( true ) ;
2014-02-10 02:10:30 +01:00
}
2017-05-24 12:00:55 +02:00
debug_menu - > get_popup ( ) - > set_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_FILE_SERVER ) , ! ischecked ) ;
2017-02-08 06:18:48 +01:00
EditorSettings : : get_singleton ( ) - > set_project_metadata ( " debug_options " , " run_file_server " , ! ischecked ) ;
2014-02-10 02:10:30 +01:00
} break ;
2015-08-02 17:29:37 +02:00
case RUN_LIVE_DEBUG : {
2017-05-24 12:00:55 +02:00
bool ischecked = debug_menu - > get_popup ( ) - > is_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_LIVE_DEBUG ) ) ;
2015-08-06 07:37:40 +02:00
2017-05-24 12:00:55 +02:00
debug_menu - > get_popup ( ) - > set_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_LIVE_DEBUG ) , ! ischecked ) ;
2015-08-06 07:37:40 +02:00
ScriptEditor : : get_singleton ( ) - > get_debugger ( ) - > set_live_debugging ( ! ischecked ) ;
2017-02-08 06:18:48 +01:00
EditorSettings : : get_singleton ( ) - > set_project_metadata ( " debug_options " , " run_live_debug " , ! ischecked ) ;
2015-08-02 17:29:37 +02:00
} break ;
2015-08-06 07:37:40 +02:00
case RUN_DEPLOY_REMOTE_DEBUG : {
2017-05-24 12:00:55 +02:00
bool ischecked = debug_menu - > get_popup ( ) - > is_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_DEPLOY_REMOTE_DEBUG ) ) ;
debug_menu - > get_popup ( ) - > set_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_DEPLOY_REMOTE_DEBUG ) , ! ischecked ) ;
2015-08-06 07:37:40 +02:00
run_native - > set_deploy_debug_remote ( ! ischecked ) ;
2017-02-08 06:18:48 +01:00
EditorSettings : : get_singleton ( ) - > set_project_metadata ( " debug_options " , " run_deploy_remote_debug " , ! ischecked ) ;
2015-08-06 07:37:40 +02:00
2014-02-10 02:10:30 +01:00
} break ;
2015-09-20 18:03:46 +02:00
case RUN_DEBUG_COLLISONS : {
2017-05-24 12:00:55 +02:00
bool ischecked = debug_menu - > get_popup ( ) - > is_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_DEBUG_COLLISONS ) ) ;
debug_menu - > get_popup ( ) - > set_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_DEBUG_COLLISONS ) , ! ischecked ) ;
2015-09-20 18:03:46 +02:00
run_native - > set_debug_collisions ( ! ischecked ) ;
editor_run . set_debug_collisions ( ! ischecked ) ;
2017-02-08 06:18:48 +01:00
EditorSettings : : get_singleton ( ) - > set_project_metadata ( " debug_options " , " run_debug_collisons " , ! ischecked ) ;
2015-09-20 18:03:46 +02:00
} break ;
case RUN_DEBUG_NAVIGATION : {
2017-05-24 12:00:55 +02:00
bool ischecked = debug_menu - > get_popup ( ) - > is_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_DEBUG_NAVIGATION ) ) ;
debug_menu - > get_popup ( ) - > set_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_DEBUG_NAVIGATION ) , ! ischecked ) ;
2015-09-20 18:03:46 +02:00
run_native - > set_debug_navigation ( ! ischecked ) ;
editor_run . set_debug_navigation ( ! ischecked ) ;
2017-02-08 06:18:48 +01:00
EditorSettings : : get_singleton ( ) - > set_project_metadata ( " debug_options " , " run_debug_navigation " , ! ischecked ) ;
2015-09-20 18:03:46 +02:00
} break ;
2021-09-26 21:31:17 +02:00
case RUN_DEBUG_SHADER_FALLBACKS : {
bool ischecked = debug_menu - > get_popup ( ) - > is_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_DEBUG_SHADER_FALLBACKS ) ) ;
debug_menu - > get_popup ( ) - > set_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_DEBUG_SHADER_FALLBACKS ) , ! ischecked ) ;
run_native - > set_debug_shader_fallbacks ( ! ischecked ) ;
editor_run . set_debug_shader_fallbacks ( ! ischecked ) ;
EditorSettings : : get_singleton ( ) - > set_project_metadata ( " debug_options " , " run_debug_shader_fallbacks " , ! ischecked ) ;
} break ;
2016-06-02 01:22:02 +02:00
case RUN_RELOAD_SCRIPTS : {
2017-05-24 12:00:55 +02:00
bool ischecked = debug_menu - > get_popup ( ) - > is_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_RELOAD_SCRIPTS ) ) ;
debug_menu - > get_popup ( ) - > set_item_checked ( debug_menu - > get_popup ( ) - > get_item_index ( RUN_RELOAD_SCRIPTS ) , ! ischecked ) ;
2016-06-03 17:34:11 +02:00
ScriptEditor : : get_singleton ( ) - > set_live_auto_reload_running_scripts ( ! ischecked ) ;
2017-02-08 06:18:48 +01:00
EditorSettings : : get_singleton ( ) - > set_project_metadata ( " debug_options " , " run_reload_scripts " , ! ischecked ) ;
2016-06-02 01:22:02 +02:00
} break ;
2018-12-11 16:52:25 +01:00
case SETTINGS_UPDATE_CONTINUOUSLY : {
EditorSettings : : get_singleton ( ) - > set ( " interface/editor/update_continuously " , true ) ;
_update_update_spinner ( ) ;
2018-08-05 16:47:41 +02:00
show_accept ( TTR ( " This option is deprecated. Situations where refresh must be forced are now considered a bug. Please report. " ) , TTR ( " OK " ) ) ;
2014-02-10 02:10:30 +01:00
} break ;
2018-12-11 16:52:25 +01:00
case SETTINGS_UPDATE_WHEN_CHANGED : {
EditorSettings : : get_singleton ( ) - > set ( " interface/editor/update_continuously " , false ) ;
2021-10-05 20:05:57 +02:00
EditorSettings : : get_singleton ( ) - > set ( " interface/editor/update_vital_only " , false ) ;
_update_update_spinner ( ) ;
} break ;
case SETTINGS_UPDATE_VITAL_ONLY : {
EditorSettings : : get_singleton ( ) - > set ( " interface/editor/update_continuously " , false ) ;
EditorSettings : : get_singleton ( ) - > set ( " interface/editor/update_vital_only " , true ) ;
2018-12-11 16:52:25 +01:00
_update_update_spinner ( ) ;
2014-02-10 02:10:30 +01:00
} break ;
2017-03-05 16:44:50 +01:00
case SETTINGS_UPDATE_SPINNER_HIDE : {
2018-12-11 16:52:25 +01:00
EditorSettings : : get_singleton ( ) - > set ( " interface/editor/show_update_spinner " , false ) ;
_update_update_spinner ( ) ;
2017-03-05 16:44:50 +01:00
} break ;
2014-02-10 02:10:30 +01:00
case SETTINGS_PREFERENCES : {
settings_config_dialog - > popup_edit_settings ( ) ;
} break ;
2018-07-25 19:53:12 +02:00
case SETTINGS_EDITOR_DATA_FOLDER : {
2018-09-11 20:32:08 +02:00
OS : : get_singleton ( ) - > shell_open ( String ( " file:// " ) + EditorSettings : : get_singleton ( ) - > get_data_dir ( ) ) ;
2018-07-25 19:53:12 +02:00
} break ;
case SETTINGS_EDITOR_CONFIG_FOLDER : {
2018-09-11 20:32:08 +02:00
OS : : get_singleton ( ) - > shell_open ( String ( " file:// " ) + EditorSettings : : get_singleton ( ) - > get_settings_dir ( ) ) ;
2018-07-25 19:53:12 +02:00
} break ;
2017-03-21 03:31:41 +01:00
case SETTINGS_MANAGE_EXPORT_TEMPLATES : {
export_template_manager - > popup_manager ( ) ;
2014-02-10 02:10:30 +01:00
2019-04-09 00:18:03 +02:00
} break ;
2021-07-15 15:12:56 +02:00
case SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE : {
custom_build_manage_templates - > hide ( ) ;
file_android_build_source - > popup_centered_ratio ( ) ;
} break ;
2019-04-09 00:18:03 +02:00
case SETTINGS_MANAGE_FEATURE_PROFILES : {
2019-04-26 21:36:44 +02:00
feature_profile_manager - > popup_centered_clamped ( Size2 ( 900 , 800 ) * EDSCALE , 0.8 ) ;
2016-09-13 14:46:17 +02:00
} break ;
2018-06-11 07:53:25 +02:00
case SETTINGS_TOGGLE_FULLSCREEN : {
2017-03-05 16:44:50 +01:00
OS : : get_singleton ( ) - > set_window_fullscreen ( ! OS : : get_singleton ( ) - > is_window_fullscreen ( ) ) ;
2016-09-13 14:46:17 +02:00
2018-12-18 14:17:43 +01:00
} break ;
2019-03-29 14:53:11 +01:00
case EDITOR_SCREENSHOT : {
screenshot_timer - > start ( ) ;
} break ;
2016-06-28 00:59:33 +02:00
case SETTINGS_PICK_MAIN_SCENE : {
file - > set_mode ( EditorFileDialog : : MODE_OPEN_FILE ) ;
List < String > extensions ;
2017-03-05 16:44:50 +01:00
ResourceLoader : : get_recognized_extensions_for_type ( " PackedScene " , & extensions ) ;
2016-06-28 00:59:33 +02:00
file - > clear_filters ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < extensions . size ( ) ; i + + ) {
file - > add_filter ( " *. " + extensions [ i ] + " ; " + extensions [ i ] . to_upper ( ) ) ;
2016-06-28 00:59:33 +02:00
}
Node * scene = editor_data . get_edited_scene_root ( ) ;
if ( scene ) {
file - > set_current_path ( scene - > get_filename ( ) ) ;
} ;
2016-06-28 12:00:18 +02:00
file - > set_title ( TTR ( " Pick a Main Scene " ) ) ;
2016-06-28 00:59:33 +02:00
file - > popup_centered_ratio ( ) ;
2014-02-10 02:10:30 +01:00
} break ;
2017-05-26 16:34:41 +02:00
case HELP_SEARCH : {
emit_signal ( " request_help_search " , " " ) ;
} break ;
case HELP_DOCS : {
2022-02-17 18:16:11 +01:00
OS : : get_singleton ( ) - > shell_open ( VERSION_DOCS_URL " / " ) ;
2017-05-26 16:34:41 +02:00
} break ;
case HELP_QA : {
OS : : get_singleton ( ) - > shell_open ( " https://godotengine.org/qa/ " ) ;
} break ;
2020-01-29 23:10:09 +01:00
case HELP_REPORT_A_BUG : {
2017-05-26 16:34:41 +02:00
OS : : get_singleton ( ) - > shell_open ( " https://github.com/godotengine/godot/issues " ) ;
} break ;
2021-06-16 02:24:34 +02:00
case HELP_SUGGEST_A_FEATURE : {
OS : : get_singleton ( ) - > shell_open ( " https://github.com/godotengine/godot-proposals#readme " ) ;
} break ;
2020-01-29 23:10:09 +01:00
case HELP_SEND_DOCS_FEEDBACK : {
OS : : get_singleton ( ) - > shell_open ( " https://github.com/godotengine/godot-docs/issues " ) ;
} break ;
2017-05-26 16:34:41 +02:00
case HELP_COMMUNITY : {
OS : : get_singleton ( ) - > shell_open ( " https://godotengine.org/community " ) ;
} break ;
case HELP_ABOUT : {
2017-07-02 20:17:47 +02:00
about - > popup_centered_minsize ( Size2 ( 780 , 500 ) * EDSCALE ) ;
2014-02-10 02:10:30 +01:00
} break ;
2021-05-15 01:57:21 +02:00
case HELP_SUPPORT_GODOT_DEVELOPMENT : {
OS : : get_singleton ( ) - > shell_open ( " https://godotengine.org/donate " ) ;
} break ;
2016-05-27 19:18:40 +02:00
2018-07-19 23:58:15 +02:00
case SET_VIDEO_DRIVER_SAVE_AND_RESTART : {
ProjectSettings : : get_singleton ( ) - > set ( " rendering/quality/driver/driver_name " , video_driver_request ) ;
ProjectSettings : : get_singleton ( ) - > save ( ) ;
2019-01-25 21:23:56 +01:00
save_all_scenes ( ) ;
restart_editor ( ) ;
2018-07-19 23:58:15 +02:00
} break ;
2016-03-09 00:00:52 +01:00
}
2014-02-10 02:10:30 +01:00
}
2019-03-29 14:53:11 +01:00
void EditorNode : : _request_screenshot ( ) {
_screenshot ( ) ;
}
void EditorNode : : _screenshot ( bool p_use_utc ) {
String name = " editor_screenshot_ " + OS : : get_singleton ( ) - > get_iso_date_time ( p_use_utc ) . replace ( " : " , " " ) + " .png " ;
NodePath path = String ( " user:// " ) + name ;
_save_screenshot ( path ) ;
2019-07-23 07:05:29 +02:00
if ( EditorSettings : : get_singleton ( ) - > get ( " interface/editor/automatically_open_screenshots " ) ) {
2019-03-29 14:53:11 +01:00
OS : : get_singleton ( ) - > shell_open ( String ( " file:// " ) + ProjectSettings : : get_singleton ( ) - > globalize_path ( path ) ) ;
}
}
void EditorNode : : _save_screenshot ( NodePath p_path ) {
Viewport * viewport = EditorInterface : : get_singleton ( ) - > get_editor_viewport ( ) - > get_viewport ( ) ;
viewport - > set_clear_mode ( Viewport : : CLEAR_MODE_ONLY_NEXT_FRAME ) ;
Ref < Image > img = viewport - > get_texture ( ) - > get_data ( ) ;
img - > flip_y ( ) ;
viewport - > set_clear_mode ( Viewport : : CLEAR_MODE_ALWAYS ) ;
Error error = img - > save_png ( p_path ) ;
2019-09-25 10:28:50 +02:00
ERR_FAIL_COND_MSG ( error ! = OK , " Cannot save screenshot to file ' " + p_path + " '. " ) ;
2019-03-29 14:53:11 +01:00
}
2018-03-17 02:50:35 +01:00
void EditorNode : : _tool_menu_option ( int p_idx ) {
switch ( tool_menu - > get_item_id ( p_idx ) ) {
case TOOLS_ORPHAN_RESOURCES : {
orphan_resources - > show ( ) ;
} break ;
case TOOLS_CUSTOM : {
if ( tool_menu - > get_item_submenu ( p_idx ) = = " " ) {
Array params = tool_menu - > get_item_metadata ( p_idx ) ;
Object * handler = ObjectDB : : get_instance ( params [ 0 ] ) ;
String callback = params [ 1 ] ;
Variant * ud = & params [ 2 ] ;
Variant : : CallError ce ;
handler - > call ( callback , ( const Variant * * ) & ud , 1 , ce ) ;
if ( ce . error ! = Variant : : CallError : : CALL_OK ) {
String err = Variant : : get_call_error_text ( handler , callback , ( const Variant * * ) & ud , 1 , ce ) ;
2021-06-16 12:56:25 +02:00
ERR_PRINT ( " Error calling function from tool menu: " + err ) ;
2018-03-17 02:50:35 +01:00
}
} // else it's a submenu so don't do anything.
} break ;
}
}
2017-07-26 13:29:45 +02:00
int EditorNode : : _next_unsaved_scene ( bool p_valid_filename , int p_start ) {
for ( int i = p_start ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( ! editor_data . get_edited_scene_root ( i ) ) {
2017-07-09 20:48:39 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2017-06-24 12:57:30 +02:00
int current = editor_data . get_edited_scene ( ) ;
bool unsaved = ( i = = current ) ? saved_version ! = editor_data . get_undo_redo ( ) . get_version ( ) : editor_data . get_scene_version ( i ) ! = 0 ;
2017-06-26 16:04:53 +02:00
if ( unsaved ) {
2017-07-26 13:29:45 +02:00
String scene_filename = editor_data . get_edited_scene_root ( i ) - > get_filename ( ) ;
2021-05-05 12:44:11 +02:00
if ( p_valid_filename & & scene_filename . length ( ) = = 0 ) {
2017-07-26 13:29:45 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2017-06-26 16:04:53 +02:00
return i ;
}
2017-06-24 12:57:30 +02:00
}
2017-06-26 16:04:53 +02:00
return - 1 ;
2017-06-24 12:57:30 +02:00
}
2019-01-17 13:09:01 +01:00
void EditorNode : : _exit_editor ( ) {
exiting = true ;
resource_preview - > stop ( ) ; //stop early to avoid crashes
2019-04-13 13:43:35 +02:00
_save_docks ( ) ;
2019-07-04 23:45:51 +02:00
2019-08-29 15:51:23 +02:00
// Dim the editor window while it's quitting to make it clearer that it's busy
dim_editor ( true , true ) ;
2019-07-04 23:45:51 +02:00
2019-01-17 13:09:01 +01:00
get_tree ( ) - > quit ( ) ;
}
2017-06-21 06:15:39 +02:00
void EditorNode : : _discard_changes ( const String & p_str ) {
switch ( current_option ) {
2017-06-26 16:04:53 +02:00
case FILE_CLOSE_ALL_AND_QUIT :
case FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER :
2022-03-23 12:07:29 +01:00
case FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT :
2017-06-21 06:15:39 +02:00
case FILE_CLOSE :
2019-04-21 11:44:21 +02:00
case FILE_CLOSE_OTHERS :
case FILE_CLOSE_RIGHT :
case FILE_CLOSE_ALL :
2017-06-21 06:15:39 +02:00
case SCENE_TAB_CLOSE : {
2019-04-10 17:21:26 +02:00
Node * scene = editor_data . get_edited_scene_root ( tab_closing ) ;
2021-05-04 16:00:45 +02:00
if ( scene ! = nullptr ) {
2019-04-10 17:21:26 +02:00
String scene_filename = scene - > get_filename ( ) ;
2019-07-31 23:49:16 +02:00
if ( scene_filename ! = " " ) {
previous_scenes . push_back ( scene_filename ) ;
}
2019-04-10 17:21:26 +02:00
}
2017-06-21 06:15:39 +02:00
_remove_scene ( tab_closing ) ;
_update_scene_tabs ( ) ;
2017-06-26 16:04:53 +02:00
2022-03-23 12:07:29 +01:00
if ( current_option = = FILE_CLOSE_ALL_AND_QUIT | | current_option = = FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER | | current_option = = FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT ) {
2020-02-19 10:36:26 +01:00
// If restore tabs is enabled, reopen the scene that has just been closed, so it's remembered properly.
if ( bool ( EDITOR_GET ( " interface/scene_tabs/restore_scenes_on_load " ) ) ) {
_menu_option_confirm ( FILE_OPEN_PREV , true ) ;
}
2017-07-26 13:29:45 +02:00
if ( _next_unsaved_scene ( false ) = = - 1 ) {
2022-03-23 12:07:29 +01:00
if ( current_option = = FILE_CLOSE_ALL_AND_RELOAD_CURRENT_PROJECT ) {
current_option = RELOAD_CURRENT_PROJECT ;
} else if ( current_option = = FILE_CLOSE_ALL_AND_QUIT ) {
current_option = FILE_QUIT ;
} else {
current_option = RUN_PROJECT_MANAGER ;
}
2017-06-26 16:04:53 +02:00
_discard_changes ( ) ;
} else {
_menu_option_confirm ( current_option , false ) ;
}
2019-04-21 11:44:21 +02:00
} else if ( current_option = = FILE_CLOSE_OTHERS | | current_option = = FILE_CLOSE_RIGHT ) {
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 ) ) {
current_option = - 1 ;
save_confirmation - > hide ( ) ;
} else {
_menu_option_confirm ( current_option , false ) ;
}
} else if ( current_option = = FILE_CLOSE_ALL & & editor_data . get_edited_scene_count ( ) > 0 ) {
_menu_option_confirm ( current_option , false ) ;
2017-06-26 16:04:53 +02:00
} else {
current_option = - 1 ;
save_confirmation - > hide ( ) ;
}
2017-06-21 06:15:39 +02:00
} break ;
2017-06-24 12:57:30 +02:00
case FILE_QUIT : {
_menu_option_confirm ( RUN_STOP , true ) ;
2019-01-17 13:09:01 +01:00
_exit_editor ( ) ;
2017-06-24 12:57:30 +02:00
} break ;
case RUN_PROJECT_MANAGER : {
_menu_option_confirm ( RUN_STOP , true ) ;
2019-01-17 13:09:01 +01:00
_exit_editor ( ) ;
2017-06-24 12:57:30 +02:00
String exec = OS : : get_singleton ( ) - > get_executable_path ( ) ;
List < String > args ;
2022-08-13 21:52:03 +02:00
const Vector < String > & forwardable_args = Main : : get_forwardable_cli_arguments ( Main : : CLI_SCOPE_TOOL ) ;
for ( int i = 0 ; i < forwardable_args . size ( ) ; i + + ) {
args . push_back ( forwardable_args [ i ] ) ;
}
2022-09-07 23:25:22 +02:00
String exec_base_dir = exec . get_base_dir ( ) ;
if ( ! exec_base_dir . empty ( ) ) {
args . push_back ( " --path " ) ;
args . push_back ( exec_base_dir ) ;
}
2017-06-21 11:09:30 +02:00
args . push_back ( " --project-manager " ) ;
2017-06-24 12:57:30 +02:00
OS : : ProcessID pid = 0 ;
Error err = OS : : get_singleton ( ) - > execute ( exec , args , false , & pid ) ;
ERR_FAIL_COND ( err ) ;
} break ;
2022-03-23 12:07:29 +01:00
case RELOAD_CURRENT_PROJECT : {
restart_editor ( ) ;
} break ;
2017-06-21 06:15:39 +02:00
}
}
2017-02-08 06:18:48 +01:00
void EditorNode : : _update_debug_options ( ) {
2017-03-05 16:44:50 +01:00
bool check_deploy_remote = EditorSettings : : get_singleton ( ) - > get_project_metadata ( " debug_options " , " run_deploy_remote_debug " , false ) ;
bool check_file_server = EditorSettings : : get_singleton ( ) - > get_project_metadata ( " debug_options " , " run_file_server " , false ) ;
bool check_debug_collisons = EditorSettings : : get_singleton ( ) - > get_project_metadata ( " debug_options " , " run_debug_collisons " , false ) ;
2017-02-08 06:18:48 +01:00
bool check_debug_navigation = EditorSettings : : get_singleton ( ) - > get_project_metadata ( " debug_options " , " run_debug_navigation " , false ) ;
2021-09-26 21:31:17 +02:00
bool check_debug_shader_fallbacks = EditorSettings : : get_singleton ( ) - > get_project_metadata ( " debug_options " , " run_debug_shader_fallbacks " , false ) ;
2020-05-29 22:11:34 +02:00
bool check_live_debug = EditorSettings : : get_singleton ( ) - > get_project_metadata ( " debug_options " , " run_live_debug " , true ) ;
bool check_reload_scripts = EditorSettings : : get_singleton ( ) - > get_project_metadata ( " debug_options " , " run_reload_scripts " , true ) ;
2017-02-08 06:18:48 +01:00
2021-05-05 12:44:11 +02:00
if ( check_deploy_remote ) {
2021-05-04 14:28:27 +02:00
_menu_option_confirm ( RUN_DEPLOY_REMOTE_DEBUG , true ) ;
2021-05-05 12:44:11 +02:00
}
if ( check_file_server ) {
2021-05-04 14:28:27 +02:00
_menu_option_confirm ( RUN_FILE_SERVER , true ) ;
2021-05-05 12:44:11 +02:00
}
if ( check_debug_collisons ) {
2021-05-04 14:28:27 +02:00
_menu_option_confirm ( RUN_DEBUG_COLLISONS , true ) ;
2021-05-05 12:44:11 +02:00
}
if ( check_debug_navigation ) {
2021-05-04 14:28:27 +02:00
_menu_option_confirm ( RUN_DEBUG_NAVIGATION , true ) ;
2021-05-05 12:44:11 +02:00
}
2021-09-26 21:31:17 +02:00
if ( check_debug_shader_fallbacks ) {
_menu_option_confirm ( RUN_DEBUG_SHADER_FALLBACKS , true ) ;
}
2021-05-05 12:44:11 +02:00
if ( check_live_debug ) {
2021-05-04 14:28:27 +02:00
_menu_option_confirm ( RUN_LIVE_DEBUG , true ) ;
2021-05-05 12:44:11 +02:00
}
if ( check_reload_scripts ) {
2021-05-04 14:28:27 +02:00
_menu_option_confirm ( RUN_RELOAD_SCRIPTS , true ) ;
2021-05-05 12:44:11 +02:00
}
2017-02-08 06:18:48 +01:00
}
2014-02-10 02:10:30 +01:00
2019-04-10 17:21:26 +02:00
void EditorNode : : _update_file_menu_opened ( ) {
Ref < ShortCut > close_scene_sc = ED_GET_SHORTCUT ( " editor/close_scene " ) ;
close_scene_sc - > set_name ( TTR ( " Close Scene " ) ) ;
Ref < ShortCut > reopen_closed_scene_sc = ED_GET_SHORTCUT ( " editor/reopen_closed_scene " ) ;
reopen_closed_scene_sc - > set_name ( TTR ( " Reopen Closed Scene " ) ) ;
2021-08-17 05:41:49 +02:00
2019-04-10 17:21:26 +02:00
PopupMenu * pop = file_menu - > get_popup ( ) ;
pop - > set_item_disabled ( pop - > get_item_index ( FILE_OPEN_PREV ) , previous_scenes . empty ( ) ) ;
2021-08-17 05:41:49 +02:00
const UndoRedo & undo_redo = editor_data . get_undo_redo ( ) ;
pop - > set_item_disabled ( pop - > get_item_index ( EDIT_UNDO ) , ! undo_redo . has_undo ( ) ) ;
pop - > set_item_disabled ( pop - > get_item_index ( EDIT_REDO ) , ! undo_redo . has_redo ( ) ) ;
2019-04-10 17:21:26 +02:00
}
void EditorNode : : _update_file_menu_closed ( ) {
PopupMenu * pop = file_menu - > get_popup ( ) ;
pop - > set_item_disabled ( pop - > get_item_index ( FILE_OPEN_PREV ) , false ) ;
}
2017-03-05 16:44:50 +01:00
Control * EditorNode : : get_viewport ( ) {
2014-02-10 02:10:30 +01:00
return viewport ;
}
void EditorNode : : _editor_select ( int p_which ) {
2017-03-05 16:44:50 +01:00
static bool selecting = false ;
2021-05-05 12:44:11 +02:00
if ( selecting | | changing_scene ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_which , editor_table . size ( ) ) ;
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( ! main_editor_buttons [ p_which ] - > is_visible ( ) ) { //button hidden, no editor
2019-04-09 00:18:03 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2019-04-09 00:18:03 +02:00
selecting = true ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < main_editor_buttons . size ( ) ; i + + ) {
main_editor_buttons [ i ] - > set_pressed ( i = = p_which ) ;
2015-11-18 08:47:41 +01:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
selecting = false ;
2014-02-10 02:10:30 +01:00
EditorPlugin * new_editor = editor_table [ p_which ] ;
ERR_FAIL_COND ( ! new_editor ) ;
2021-05-05 12:44:11 +02:00
if ( editor_plugin_screen = = new_editor ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
if ( editor_plugin_screen ) {
editor_plugin_screen - > make_visible ( false ) ;
}
2017-03-05 16:44:50 +01:00
editor_plugin_screen = new_editor ;
2014-02-10 02:10:30 +01:00
editor_plugin_screen - > make_visible ( true ) ;
editor_plugin_screen - > selected_notify ( ) ;
2017-04-25 13:48:35 +02:00
2017-07-06 09:18:20 +02:00
int plugin_count = editor_data . get_editor_plugin_count ( ) ;
for ( int i = 0 ; i < plugin_count ; i + + ) {
editor_data . get_editor_plugin ( i ) - > notify_main_screen_changed ( editor_plugin_screen - > get_name ( ) ) ;
}
2017-09-29 18:52:56 +02:00
if ( EditorSettings : : get_singleton ( ) - > get ( " interface/editor/separate_distraction_mode " ) ) {
2017-04-25 13:48:35 +02:00
if ( p_which = = EDITOR_SCRIPT ) {
set_distraction_free_mode ( script_distraction ) ;
} else {
set_distraction_free_mode ( scene_distraction ) ;
}
}
2014-02-10 02:10:30 +01:00
}
2019-08-05 19:57:23 +02:00
void EditorNode : : select_editor_by_name ( const String & p_name ) {
ERR_FAIL_COND ( p_name = = " " ) ;
for ( int i = 0 ; i < main_editor_buttons . size ( ) ; i + + ) {
if ( main_editor_buttons [ i ] - > get_text ( ) = = p_name ) {
_editor_select ( i ) ;
return ;
}
}
2019-08-15 04:57:49 +02:00
ERR_FAIL_MSG ( " The editor name ' " + p_name + " ' was not found. " ) ;
2019-08-05 19:57:23 +02:00
}
2018-06-11 02:59:53 +02:00
void EditorNode : : add_editor_plugin ( EditorPlugin * p_editor , bool p_config_changed ) {
2014-02-10 02:10:30 +01:00
if ( p_editor - > has_main_screen ( ) ) {
2017-03-05 16:44:50 +01:00
ToolButton * tb = memnew ( ToolButton ) ;
2015-11-18 08:47:41 +01:00
tb - > set_toggle_mode ( true ) ;
2017-03-05 16:44:50 +01:00
tb - > connect ( " pressed " , singleton , " _editor_select " , varray ( singleton - > main_editor_buttons . size ( ) ) ) ;
2017-05-02 23:02:06 +02:00
tb - > set_text ( p_editor - > get_name ( ) ) ;
2017-12-06 23:27:45 +01:00
Ref < Texture > icon = p_editor - > get_icon ( ) ;
if ( icon . is_valid ( ) ) {
tb - > set_icon ( icon ) ;
} else if ( singleton - > gui_base - > has_icon ( p_editor - > get_name ( ) , " EditorIcons " ) ) {
tb - > set_icon ( singleton - > gui_base - > get_icon ( p_editor - > get_name ( ) , " EditorIcons " ) ) ;
}
2017-05-02 22:13:12 +02:00
tb - > set_name ( p_editor - > get_name ( ) ) ;
2015-11-18 08:47:41 +01:00
singleton - > main_editor_buttons . push_back ( tb ) ;
singleton - > main_editor_button_vb - > add_child ( tb ) ;
2014-02-10 02:10:30 +01:00
singleton - > editor_table . push_back ( p_editor ) ;
2016-09-13 14:46:17 +02:00
singleton - > distraction_free - > raise ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
singleton - > editor_data . add_editor_plugin ( p_editor ) ;
2014-02-10 02:10:30 +01:00
singleton - > add_child ( p_editor ) ;
2021-05-05 12:44:11 +02:00
if ( p_config_changed ) {
2018-06-11 02:59:53 +02:00
p_editor - > enable_plugin ( ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
2018-06-11 02:59:53 +02:00
void EditorNode : : remove_editor_plugin ( EditorPlugin * p_editor , bool p_config_changed ) {
2014-02-10 02:10:30 +01:00
if ( p_editor - > has_main_screen ( ) ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < singleton - > main_editor_buttons . size ( ) ; i + + ) {
if ( p_editor - > get_name ( ) = = singleton - > main_editor_buttons [ i ] - > get_text ( ) ) {
2016-09-22 00:17:55 +02:00
if ( singleton - > main_editor_buttons [ i ] - > is_pressed ( ) ) {
singleton - > _editor_select ( EDITOR_SCRIPT ) ;
}
2017-03-05 16:44:50 +01:00
memdelete ( singleton - > main_editor_buttons [ i ] ) ;
2015-11-18 08:47:41 +01:00
singleton - > main_editor_buttons . remove ( i ) ;
2014-02-10 02:10:30 +01:00
break ;
}
}
singleton - > editor_table . erase ( p_editor ) ;
}
2016-06-19 00:29:16 +02:00
p_editor - > make_visible ( false ) ;
p_editor - > clear ( ) ;
2021-05-05 12:44:11 +02:00
if ( p_config_changed ) {
2018-06-11 02:59:53 +02:00
p_editor - > disable_plugin ( ) ;
2021-05-05 12:44:11 +02:00
}
2021-05-17 10:46:59 +02:00
singleton - > editor_plugins_over - > remove_plugin ( p_editor ) ;
singleton - > editor_plugins_force_over - > remove_plugin ( p_editor ) ;
singleton - > editor_plugins_force_input_forwarding - > remove_plugin ( p_editor ) ;
2014-02-10 02:10:30 +01:00
singleton - > remove_child ( p_editor ) ;
2017-03-05 16:44:50 +01:00
singleton - > editor_data . remove_editor_plugin ( p_editor ) ;
2014-02-10 02:10:30 +01:00
}
2016-02-28 03:10:44 +01:00
void EditorNode : : _update_addon_config ( ) {
2021-05-05 12:44:11 +02:00
if ( _initializing_addons ) {
2016-02-28 03:10:44 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2016-02-28 03:10:44 +01:00
Vector < String > enabled_addons ;
2017-03-05 16:44:50 +01:00
for ( Map < String , EditorPlugin * > : : Element * E = plugin_addons . front ( ) ; E ; E = E - > next ( ) ) {
2016-02-28 03:10:44 +01:00
enabled_addons . push_back ( E - > key ( ) ) ;
}
2017-03-05 16:44:50 +01:00
if ( enabled_addons . size ( ) = = 0 ) {
2017-07-19 22:00:46 +02:00
ProjectSettings : : get_singleton ( ) - > set ( " editor_plugins/enabled " , Variant ( ) ) ;
2016-02-28 03:10:44 +01:00
} else {
2017-07-19 22:00:46 +02:00
ProjectSettings : : get_singleton ( ) - > set ( " editor_plugins/enabled " , enabled_addons ) ;
2016-02-28 03:10:44 +01:00
}
project_settings - > queue_save ( ) ;
}
2021-02-24 18:29:58 +01:00
void EditorNode : : set_addon_plugin_enabled ( String p_addon , bool p_enabled , bool p_config_changed ) {
if ( ! p_addon . begins_with ( " res:// " ) ) {
p_addon = _to_absolute_plugin_path ( p_addon ) ;
}
2016-02-28 03:10:44 +01:00
ERR_FAIL_COND ( p_enabled & & plugin_addons . has ( p_addon ) ) ;
ERR_FAIL_COND ( ! p_enabled & & ! plugin_addons . has ( p_addon ) ) ;
if ( ! p_enabled ) {
EditorPlugin * addon = plugin_addons [ p_addon ] ;
2018-06-11 02:59:53 +02:00
remove_editor_plugin ( addon , p_config_changed ) ;
2016-02-28 03:10:44 +01:00
memdelete ( addon ) ; //bye
plugin_addons . erase ( p_addon ) ;
_update_addon_config ( ) ;
return ;
}
Ref < ConfigFile > cf ;
cf . instance ( ) ;
2021-01-19 17:41:12 +01:00
if ( ! DirAccess : : exists ( p_addon . get_base_dir ( ) ) ) {
2021-05-09 14:17:15 +02:00
_remove_plugin_from_enabled ( p_addon ) ;
WARN_PRINT ( " Addon ' " + p_addon + " ' failed to load. No directory found. Removing from enabled plugins. " ) ;
2019-02-17 00:53:14 +01:00
return ;
}
2021-01-19 17:41:12 +01:00
Error err = cf - > load ( p_addon ) ;
2017-03-05 16:44:50 +01:00
if ( err ! = OK ) {
2021-01-19 17:41:12 +01:00
show_warning ( vformat ( TTR ( " Unable to enable addon plugin at: '%s' parsing of config failed. " ) , p_addon ) ) ;
2016-02-28 03:10:44 +01:00
return ;
}
2017-03-05 16:44:50 +01:00
if ( ! cf - > has_section_key ( " plugin " , " script " ) ) {
2021-01-19 17:41:12 +01:00
show_warning ( vformat ( TTR ( " Unable to find script field for addon plugin at: '%s'. " ) , p_addon ) ) ;
2016-02-28 03:10:44 +01:00
return ;
}
2019-08-15 19:40:22 +02:00
String script_path = cf - > get_value ( " plugin " , " script " ) ;
Ref < Script > script ; // We need to save it for creating "ep" below.
2016-02-28 03:10:44 +01:00
2019-08-15 19:40:22 +02:00
// Only try to load the script if it has a name. Else, the plugin has no init script.
if ( script_path . length ( ) > 0 ) {
2021-01-19 17:41:12 +01:00
script_path = p_addon . get_base_dir ( ) . plus_file ( script_path ) ;
2019-08-15 19:40:22 +02:00
script = ResourceLoader : : load ( script_path ) ;
2016-02-28 03:10:44 +01:00
2019-08-15 19:40:22 +02:00
if ( script . is_null ( ) ) {
show_warning ( vformat ( TTR ( " Unable to load addon script from path: '%s'. " ) , script_path ) ) ;
return ;
}
2016-02-28 03:10:44 +01:00
2019-08-15 19:40:22 +02:00
// Errors in the script cause the base_type to be an empty string.
if ( String ( script - > get_instance_base_type ( ) ) = = " " ) {
2021-05-18 12:09:09 +02:00
show_warning ( vformat ( TTR ( " Unable to load addon script from path: '%s'. This might be due to a code error in that script. \n Disabling the addon at '%s' to prevent further errors. " ) , script_path , p_addon ) ) ;
2021-05-09 14:17:15 +02:00
_remove_plugin_from_enabled ( p_addon ) ;
2019-08-15 19:40:22 +02:00
return ;
}
2018-10-13 14:20:18 +02:00
2019-08-15 19:40:22 +02:00
// Plugin init scripts must inherit from EditorPlugin and be tools.
if ( String ( script - > get_instance_base_type ( ) ) ! = " EditorPlugin " ) {
show_warning ( vformat ( TTR ( " Unable to load addon script from path: '%s' Base type is not EditorPlugin. " ) , script_path ) ) ;
return ;
}
2016-02-28 03:10:44 +01:00
2019-08-15 19:40:22 +02:00
if ( ! script - > is_tool ( ) ) {
show_warning ( vformat ( TTR ( " Unable to load addon script from path: '%s' Script is not in tool mode. " ) , script_path ) ) ;
return ;
}
2016-02-28 03:10:44 +01:00
}
2017-03-05 16:44:50 +01:00
EditorPlugin * ep = memnew ( EditorPlugin ) ;
2016-02-28 03:10:44 +01:00
ep - > set_script ( script . get_ref_ptr ( ) ) ;
2017-03-05 16:44:50 +01:00
plugin_addons [ p_addon ] = ep ;
2018-06-11 02:59:53 +02:00
add_editor_plugin ( ep , p_config_changed ) ;
2016-02-28 03:10:44 +01:00
_update_addon_config ( ) ;
}
2017-03-05 16:44:50 +01:00
bool EditorNode : : is_addon_plugin_enabled ( const String & p_addon ) const {
2021-02-24 18:29:58 +01:00
if ( p_addon . begins_with ( " res:// " ) ) {
return plugin_addons . has ( p_addon ) ;
}
return plugin_addons . has ( _to_absolute_plugin_path ( p_addon ) ) ;
2016-02-28 03:10:44 +01:00
}
2019-06-04 05:36:23 +02:00
void EditorNode : : _remove_edited_scene ( bool p_change_tab ) {
2015-06-22 05:03:19 +02:00
int new_index = editor_data . get_edited_scene ( ) ;
2017-03-05 16:44:50 +01:00
int old_index = new_index ;
2015-06-22 05:03:19 +02:00
2017-03-05 16:44:50 +01:00
if ( new_index > 0 ) {
new_index = new_index - 1 ;
} else if ( editor_data . get_edited_scene_count ( ) > 1 ) {
new_index = 1 ;
2015-06-22 05:03:19 +02:00
} else {
editor_data . add_edited_scene ( - 1 ) ;
2017-03-05 16:44:50 +01:00
new_index = 1 ;
2015-06-22 05:03:19 +02:00
}
2021-05-05 12:44:11 +02:00
if ( p_change_tab ) {
2021-05-04 14:28:27 +02:00
_scene_tab_changed ( new_index ) ;
2021-05-05 12:44:11 +02:00
}
2015-06-22 05:03:19 +02:00
editor_data . remove_scene ( old_index ) ;
2018-11-18 21:07:38 +01:00
editor_data . get_undo_redo ( ) . clear_history ( false ) ;
2015-06-22 05:03:19 +02:00
_update_title ( ) ;
_update_scene_tabs ( ) ;
}
2015-10-22 00:23:42 +02:00
2019-06-04 05:36:23 +02:00
void EditorNode : : _remove_scene ( int index , bool p_change_tab ) {
2022-05-05 14:27:29 +02:00
// Clear icon cache in case some scripts are no longer needed.
script_icon_cache . clear ( ) ;
2015-10-22 00:23:42 +02:00
if ( editor_data . get_edited_scene ( ) = = index ) {
//Scene to remove is current scene
2019-06-04 05:36:23 +02:00
_remove_edited_scene ( p_change_tab ) ;
2017-03-05 16:44:50 +01:00
} else {
2018-01-09 13:42:45 +01:00
//Scene to remove is not active scene
2015-10-22 00:23:42 +02:00
editor_data . remove_scene ( index ) ;
}
}
2014-02-10 02:10:30 +01:00
void EditorNode : : set_edited_scene ( Node * p_scene ) {
2015-06-22 05:03:19 +02:00
if ( get_editor_data ( ) . get_edited_scene_root ( ) ) {
2021-05-05 12:44:11 +02:00
if ( get_editor_data ( ) . get_edited_scene_root ( ) - > get_parent ( ) = = scene_root ) {
2015-06-22 05:03:19 +02:00
scene_root - > remove_child ( get_editor_data ( ) . get_edited_scene_root ( ) ) ;
2021-05-05 12:44:11 +02:00
}
2016-03-09 00:00:52 +01:00
}
2015-06-22 05:03:19 +02:00
get_editor_data ( ) . set_edited_scene_root ( p_scene ) ;
2016-03-09 00:00:52 +01:00
2021-05-05 12:44:11 +02:00
if ( Object : : cast_to < Popup > ( p_scene ) ) {
2017-08-24 22:58:51 +02:00
Object : : cast_to < Popup > ( p_scene ) - > show ( ) ; //show popups
2021-05-05 12:44:11 +02:00
}
2015-06-22 05:03:19 +02:00
scene_tree_dock - > set_edited_scene ( p_scene ) ;
2021-05-05 12:44:11 +02:00
if ( get_tree ( ) ) {
2015-06-22 05:03:19 +02:00
get_tree ( ) - > set_edited_scene_root ( p_scene ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2015-06-22 05:03:19 +02:00
if ( p_scene ) {
2021-05-05 12:44:11 +02:00
if ( p_scene - > get_parent ( ) ! = scene_root ) {
2014-02-10 02:10:30 +01:00
scene_root - > add_child ( p_scene ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
2015-11-18 08:47:41 +01:00
int EditorNode : : _get_current_main_editor ( ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < editor_table . size ( ) ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( editor_table [ i ] = = editor_plugin_screen ) {
2015-11-18 08:47:41 +01:00
return i ;
2021-05-05 12:44:11 +02:00
}
2015-11-18 08:47:41 +01:00
}
return 0 ;
}
2015-06-22 05:03:19 +02:00
Dictionary EditorNode : : _get_main_scene_state ( ) {
Dictionary state ;
2017-03-05 16:44:50 +01:00
state [ " main_tab " ] = _get_current_main_editor ( ) ;
state [ " scene_tree_offset " ] = scene_tree_dock - > get_tree_editor ( ) - > get_scene_tree ( ) - > get_vscroll_bar ( ) - > get_value ( ) ;
2018-05-15 22:12:35 +02:00
state [ " property_edit_offset " ] = get_inspector ( ) - > get_scroll_offset ( ) ;
2017-03-05 16:44:50 +01:00
state [ " saved_version " ] = saved_version ;
state [ " node_filter " ] = scene_tree_dock - > get_filter ( ) ;
2015-06-22 05:03:19 +02:00
return state ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _set_main_scene_state ( Dictionary p_state , Node * p_for_scene ) {
2021-05-05 12:44:11 +02:00
if ( get_edited_scene ( ) ! = p_for_scene & & p_for_scene ! = nullptr ) {
2016-06-28 23:53:31 +02:00
return ; //not for this scene
2021-05-05 12:44:11 +02:00
}
2015-06-22 05:03:19 +02:00
2017-03-05 16:44:50 +01:00
changing_scene = false ;
2015-06-22 05:03:19 +02:00
2017-09-08 23:45:04 +02:00
int current = - 1 ;
for ( int i = 0 ; i < editor_table . size ( ) ; i + + ) {
if ( editor_plugin_screen = = editor_table [ i ] ) {
current = i ;
break ;
2015-11-17 13:46:08 +01:00
}
2017-09-08 23:45:04 +02:00
}
2015-11-17 13:46:08 +01:00
2017-09-08 23:45:04 +02:00
if ( p_state . has ( " editor_index " ) ) {
int index = p_state [ " editor_index " ] ;
2018-02-21 17:30:55 +01:00
if ( current < 2 ) { //if currently in spatial/2d, only switch to spatial/2d. if currently in script, stay there
2017-09-04 23:00:09 +02:00
if ( index < 2 | | ! get_edited_scene ( ) ) {
_editor_select ( index ) ;
2017-09-08 23:45:04 +02:00
}
}
}
if ( get_edited_scene ( ) ) {
if ( current < 2 ) {
//use heuristic instead
int n2d = 0 , n3d = 0 ;
_find_node_types ( get_edited_scene ( ) , n2d , n3d ) ;
if ( n2d > n3d ) {
_editor_select ( EDITOR_2D ) ;
} else if ( n3d > n2d ) {
_editor_select ( EDITOR_3D ) ;
2015-11-17 13:46:08 +01:00
}
}
}
2021-05-05 12:44:11 +02:00
if ( p_state . has ( " scene_tree_offset " ) ) {
2017-01-04 05:16:14 +01:00
scene_tree_dock - > get_tree_editor ( ) - > get_scene_tree ( ) - > get_vscroll_bar ( ) - > set_value ( p_state [ " scene_tree_offset " ] ) ;
2021-05-05 12:44:11 +02:00
}
if ( p_state . has ( " property_edit_offset " ) ) {
2018-05-15 22:12:35 +02:00
get_inspector ( ) - > set_scroll_offset ( p_state [ " property_edit_offset " ] ) ;
2021-05-05 12:44:11 +02:00
}
2015-06-22 05:03:19 +02:00
2021-05-05 12:44:11 +02:00
if ( p_state . has ( " node_filter " ) ) {
2016-05-16 17:23:40 +02:00
scene_tree_dock - > set_filter ( p_state [ " node_filter " ] ) ;
2021-05-05 12:44:11 +02:00
}
2015-06-22 05:03:19 +02:00
2015-11-17 13:46:08 +01:00
//this should only happen at the very end
ScriptEditor : : get_singleton ( ) - > get_debugger ( ) - > update_live_edit_root ( ) ;
2017-03-05 16:44:50 +01:00
ScriptEditor : : get_singleton ( ) - > set_scene_root_script ( editor_data . get_scene_root_script ( editor_data . get_edited_scene ( ) ) ) ;
2015-12-09 13:08:41 +01:00
editor_data . notify_edited_scene_changed ( ) ;
2015-06-22 05:03:19 +02:00
}
void EditorNode : : set_current_version ( uint64_t p_version ) {
2017-03-05 16:44:50 +01:00
saved_version = p_version ;
2015-06-22 05:03:19 +02:00
editor_data . set_edited_scene_version ( p_version ) ;
}
bool EditorNode : : is_changing_scene ( ) const {
return changing_scene ;
}
2015-12-14 00:39:01 +01:00
void EditorNode : : _clear_undo_history ( ) {
2019-03-01 17:20:30 +01:00
get_undo_redo ( ) - > clear_history ( false ) ;
2015-12-14 00:39:01 +01:00
}
2015-06-22 05:03:19 +02:00
void EditorNode : : set_current_scene ( int p_idx ) {
2019-09-10 14:43:46 +02:00
//Save the folding in case the scene gets reloaded.
2021-05-05 12:44:11 +02:00
if ( editor_data . get_scene_path ( p_idx ) ! = " " & & editor_data . get_edited_scene_root ( p_idx ) ) {
2019-09-10 14:43:46 +02:00
editor_folding . save_scene_folding ( editor_data . get_edited_scene_root ( p_idx ) , editor_data . get_scene_path ( p_idx ) ) ;
2021-05-05 12:44:11 +02:00
}
2019-09-10 14:43:46 +02:00
2015-12-14 00:39:01 +01:00
if ( editor_data . check_and_update_scene ( p_idx ) ) {
2021-05-05 12:44:11 +02:00
if ( editor_data . get_scene_path ( p_idx ) ! = " " ) {
2019-09-10 14:43:46 +02:00
editor_folding . load_scene_folding ( editor_data . get_edited_scene_root ( p_idx ) , editor_data . get_scene_path ( p_idx ) ) ;
2021-05-05 12:44:11 +02:00
}
2019-09-10 14:43:46 +02:00
2015-12-14 00:39:01 +01:00
call_deferred ( " _clear_undo_history " ) ;
}
2017-03-05 16:44:50 +01:00
changing_scene = true ;
editor_data . save_edited_scene_state ( editor_selection , & editor_history , _get_main_scene_state ( ) ) ;
2015-06-22 05:03:19 +02:00
if ( get_editor_data ( ) . get_edited_scene_root ( ) ) {
2021-05-05 12:44:11 +02:00
if ( get_editor_data ( ) . get_edited_scene_root ( ) - > get_parent ( ) = = scene_root ) {
2015-06-22 05:03:19 +02:00
scene_root - > remove_child ( get_editor_data ( ) . get_edited_scene_root ( ) ) ;
2021-05-05 12:44:11 +02:00
}
2015-06-22 05:03:19 +02:00
}
editor_selection - > clear ( ) ;
editor_data . set_edited_scene ( p_idx ) ;
2017-03-05 16:44:50 +01:00
Node * new_scene = editor_data . get_edited_scene_root ( ) ;
2015-06-22 05:03:19 +02:00
2021-05-05 12:44:11 +02:00
if ( Object : : cast_to < Popup > ( new_scene ) ) {
2017-08-24 22:58:51 +02:00
Object : : cast_to < Popup > ( new_scene ) - > show ( ) ; //show popups
2021-05-05 12:44:11 +02:00
}
2015-06-22 05:03:19 +02:00
scene_tree_dock - > set_edited_scene ( new_scene ) ;
2021-05-05 12:44:11 +02:00
if ( get_tree ( ) ) {
2015-06-22 05:03:19 +02:00
get_tree ( ) - > set_edited_scene_root ( new_scene ) ;
2021-05-05 12:44:11 +02:00
}
2015-06-22 05:03:19 +02:00
if ( new_scene ) {
2021-05-05 12:44:11 +02:00
if ( new_scene - > get_parent ( ) ! = scene_root ) {
2015-06-22 05:03:19 +02:00
scene_root - > add_child ( new_scene ) ;
2021-05-05 12:44:11 +02:00
}
2015-06-22 05:03:19 +02:00
}
2017-03-05 16:44:50 +01:00
Dictionary state = editor_data . restore_edited_scene_state ( editor_selection , & editor_history ) ;
2021-09-12 21:17:34 +02:00
_edit_current ( true ) ;
2015-06-22 05:03:19 +02:00
2018-09-11 12:28:32 +02:00
_update_title ( ) ;
2017-03-05 16:44:50 +01:00
call_deferred ( " _set_main_scene_state " , state , get_edited_scene ( ) ) ; //do after everything else is done setting up
2015-06-22 05:03:19 +02:00
}
2017-03-05 16:44:50 +01:00
bool EditorNode : : is_scene_open ( const String & p_path ) {
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( editor_data . get_scene_path ( i ) = = p_path ) {
2015-08-24 01:15:56 +02:00
return true ;
2021-05-05 12:44:11 +02:00
}
2015-08-24 01:15:56 +02:00
}
return false ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : fix_dependencies ( const String & p_for_file ) {
2015-08-24 01:15:56 +02:00
dependency_fixer - > edit ( p_for_file ) ;
}
2019-08-15 19:47:21 +02:00
int EditorNode : : new_scene ( ) {
int idx = editor_data . add_edited_scene ( - 1 ) ;
_scene_tab_changed ( idx ) ;
editor_data . clear_editor_states ( ) ;
_update_scene_tabs ( ) ;
return idx ;
}
2021-02-11 01:08:49 +01:00
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 , bool p_silent_change_tab ) {
2014-11-06 01:20:42 +01:00
if ( ! is_inside_tree ( ) ) {
2014-02-10 02:10:30 +01:00
defer_load_scene = p_scene ;
return OK ;
}
2017-03-05 16:44:50 +01:00
if ( ! p_set_inherited ) {
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
if ( editor_data . get_scene_path ( i ) = = p_scene ) {
2016-01-02 23:42:41 +01:00
_scene_tab_changed ( i ) ;
return OK ;
}
2015-06-22 05:03:19 +02:00
}
2017-02-05 00:31:15 +01:00
2017-03-05 16:44:50 +01:00
if ( ! p_force_open_imported & & FileAccess : : exists ( p_scene + " .import " ) ) {
open_imported - > set_text ( vformat ( TTR ( " Scene '%s' was automatically imported, so it can't be modified. \n To make changes to it, a new inherited scene can be created. " ) , p_scene . get_file ( ) ) ) ;
2017-02-05 00:31:15 +01:00
open_imported - > popup_centered_minsize ( ) ;
new_inherited_button - > grab_focus ( ) ;
2017-03-05 16:44:50 +01:00
open_import_request = p_scene ;
2017-02-05 00:31:15 +01:00
return OK ;
}
2015-06-22 05:03:19 +02:00
}
2021-05-05 12:44:11 +02:00
if ( p_clear_errors ) {
2016-06-26 20:37:04 +02:00
load_errors - > clear ( ) ;
2021-05-05 12:44:11 +02:00
}
2016-06-26 20:37:04 +02:00
2017-07-19 22:00:46 +02:00
String lpath = ProjectSettings : : get_singleton ( ) - > localize_path ( p_scene ) ;
2014-02-10 02:10:30 +01:00
if ( ! lpath . begins_with ( " res:// " ) ) {
2018-08-05 16:47:41 +02:00
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 " ) ) ;
2017-03-05 16:44:50 +01:00
opening_prev = false ;
2014-02-10 02:10:30 +01:00
return ERR_FILE_NOT_FOUND ;
}
2015-06-22 05:03:19 +02:00
int prev = editor_data . get_edited_scene ( ) ;
int idx = editor_data . add_edited_scene ( - 1 ) ;
2017-03-05 16:44:50 +01:00
if ( ! editor_data . get_edited_scene_root ( ) & & editor_data . get_edited_scene_count ( ) = = 2 ) {
2015-06-22 05:03:19 +02:00
_remove_edited_scene ( ) ;
2021-02-11 01:08:49 +01:00
} else if ( ! p_silent_change_tab ) {
2015-06-22 05:03:19 +02:00
_scene_tab_changed ( idx ) ;
2021-02-11 01:08:49 +01:00
} else {
set_current_scene ( idx ) ;
2015-06-22 05:03:19 +02:00
}
2015-08-24 01:15:56 +02:00
dependency_errors . clear ( ) ;
2017-08-28 05:24:50 +02:00
Error err ;
Ref < PackedScene > sdata = ResourceLoader : : load ( lpath , " " , true , & err ) ;
2014-02-10 02:10:30 +01:00
if ( ! sdata . is_valid ( ) ) {
2017-08-28 05:24:50 +02:00
_dialog_display_load_error ( lpath , err ) ;
2017-03-05 16:44:50 +01:00
opening_prev = false ;
2015-06-22 05:03:19 +02:00
2017-03-05 16:44:50 +01:00
if ( prev ! = - 1 ) {
2015-06-22 05:03:19 +02:00
set_current_scene ( prev ) ;
editor_data . remove_scene ( idx ) ;
}
2014-02-10 02:10:30 +01:00
return ERR_FILE_NOT_FOUND ;
}
2015-08-24 01:15:56 +02:00
if ( ! p_ignore_broken_deps & & dependency_errors . has ( lpath ) ) {
2017-03-05 16:44:50 +01:00
current_option = - 1 ;
2015-08-24 01:15:56 +02:00
Vector < String > errors ;
2017-03-05 16:44:50 +01:00
for ( Set < String > : : Element * E = dependency_errors [ lpath ] . front ( ) ; E ; E = E - > next ( ) ) {
2015-08-24 01:15:56 +02:00
errors . push_back ( E - > get ( ) ) ;
}
2018-11-02 04:44:40 +01:00
dependency_error - > show ( DependencyErrorDialog : : MODE_SCENE , lpath , errors ) ;
2017-03-05 16:44:50 +01:00
opening_prev = false ;
2015-08-24 01:15:56 +02:00
2017-03-05 16:44:50 +01:00
if ( prev ! = - 1 ) {
2015-08-24 01:15:56 +02:00
set_current_scene ( prev ) ;
editor_data . remove_scene ( idx ) ;
}
return ERR_FILE_MISSING_DEPENDENCIES ;
}
dependency_errors . erase ( lpath ) ; //at least not self path
2021-05-04 14:20:36 +02:00
for ( Map < String , Set < String > > : : Element * E = dependency_errors . front ( ) ; E ; E = E - > next ( ) ) {
2017-03-05 16:44:50 +01:00
String txt = vformat ( TTR ( " Scene '%s' has broken dependencies: " ) , E - > key ( ) ) + " \n " ;
for ( Set < String > : : Element * F = E - > get ( ) . front ( ) ; F ; F = F - > next ( ) ) {
txt + = " \t " + F - > get ( ) + " \n " ;
2015-08-24 01:15:56 +02:00
}
add_io_error ( txt ) ;
}
2016-01-14 15:06:20 +01:00
if ( ResourceCache : : has ( lpath ) ) {
2016-01-14 15:50:24 +01:00
//used from somewhere else? no problem! update state and replace sdata
2017-08-24 22:58:51 +02:00
Ref < PackedScene > ps = Ref < PackedScene > ( Object : : cast_to < PackedScene > ( ResourceCache : : get ( lpath ) ) ) ;
2016-01-14 15:06:20 +01:00
if ( ps . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
ps - > replace_state ( sdata - > get_state ( ) ) ;
ps - > set_last_modified_time ( sdata - > get_last_modified_time ( ) ) ;
sdata = ps ;
2016-01-14 15:06:20 +01:00
}
} else {
2017-03-05 16:44:50 +01:00
sdata - > set_path ( lpath , true ) ; //take over path
2016-01-14 15:06:20 +01:00
}
2015-06-26 06:14:31 +02:00
2021-10-26 21:12:35 +02:00
Node * new_scene = sdata - > instance ( p_set_inherited ? PackedScene : : GEN_EDIT_STATE_MAIN_INHERITED : PackedScene : : GEN_EDIT_STATE_MAIN ) ;
2014-02-10 02:10:30 +01:00
if ( ! new_scene ) {
2015-06-22 05:03:19 +02:00
sdata . unref ( ) ;
2020-06-08 13:05:09 +02:00
_dialog_display_load_error ( lpath , ERR_FILE_CORRUPT ) ;
2017-03-05 16:44:50 +01:00
opening_prev = false ;
if ( prev ! = - 1 ) {
2015-06-22 05:03:19 +02:00
set_current_scene ( prev ) ;
editor_data . remove_scene ( idx ) ;
}
2020-06-08 13:05:09 +02:00
return ERR_FILE_CORRUPT ;
2014-02-10 02:10:30 +01:00
}
2015-10-10 14:09:09 +02:00
if ( p_set_inherited ) {
Ref < SceneState > state = sdata - > get_state ( ) ;
2016-03-09 00:00:52 +01:00
state - > set_path ( lpath ) ;
2015-10-10 14:09:09 +02:00
new_scene - > set_scene_inherited_state ( state ) ;
2015-10-18 01:55:12 +02:00
new_scene - > set_filename ( String ( ) ) ;
2015-10-10 14:09:09 +02:00
}
2015-11-29 00:56:14 +01:00
new_scene - > set_scene_instance_state ( Ref < SceneState > ( ) ) ;
2015-10-10 14:09:09 +02:00
2014-02-10 02:10:30 +01:00
set_edited_scene ( new_scene ) ;
2015-12-31 04:31:00 +01:00
_get_scene_metadata ( p_scene ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
saved_version = editor_data . get_undo_redo ( ) . get_version ( ) ;
2014-02-10 02:10:30 +01:00
_update_title ( ) ;
2015-06-22 05:03:19 +02:00
_update_scene_tabs ( ) ;
2014-02-10 02:10:30 +01:00
_add_to_recent_scenes ( lpath ) ;
2018-11-25 14:46:26 +01:00
if ( editor_folding . has_folding_data ( lpath ) ) {
editor_folding . load_scene_folding ( new_scene , lpath ) ;
} else if ( EDITOR_GET ( " interface/inspector/auto_unfold_foreign_scenes " ) ) {
editor_folding . unfold_scene ( new_scene ) ;
editor_folding . save_scene_folding ( new_scene , lpath ) ;
}
2018-10-29 20:36:31 +01:00
2017-03-05 16:44:50 +01:00
prev_scene - > set_disabled ( previous_scenes . size ( ) = = 0 ) ;
opening_prev = false ;
2019-02-08 20:48:11 +01:00
scene_tree_dock - > set_selected ( new_scene ) ;
2014-02-10 02:10:30 +01:00
2015-08-02 17:29:37 +02:00
ScriptEditor : : get_singleton ( ) - > get_debugger ( ) - > update_live_edit_root ( ) ;
2014-07-07 22:44:21 +02:00
push_item ( new_scene ) ;
2014-02-10 02:10:30 +01:00
2017-11-25 00:32:54 +01:00
if ( ! restoring_scenes ) {
save_layout ( ) ;
}
2014-02-10 02:10:30 +01:00
return OK ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : open_request ( const String & p_path ) {
2019-04-10 17:21:26 +02:00
if ( ! opening_prev ) {
List < String > : : Element * prev_scene = previous_scenes . find ( p_path ) ;
2021-05-04 16:00:45 +02:00
if ( prev_scene ! = nullptr ) {
2019-04-10 17:21:26 +02:00
prev_scene - > erase ( ) ;
}
}
2015-06-22 05:03:19 +02:00
load_scene ( p_path ) ; // as it will be opened in separate tab
2014-02-10 02:10:30 +01:00
}
2016-05-12 01:57:52 +02:00
void EditorNode : : request_instance_scene ( const String & p_path ) {
scene_tree_dock - > instance ( p_path ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void EditorNode : : request_instance_scenes ( const Vector < String > & p_files ) {
2016-07-20 19:09:03 +02:00
scene_tree_dock - > instance_scenes ( p_files ) ;
}
2017-02-01 13:45:45 +01:00
ImportDock * EditorNode : : get_import_dock ( ) {
return import_dock ;
}
2017-01-21 13:07:29 +01:00
FileSystemDock * EditorNode : : get_filesystem_dock ( ) {
return filesystem_dock ;
2014-02-10 02:10:30 +01:00
}
2016-06-04 18:17:56 +02:00
SceneTreeDock * EditorNode : : get_scene_tree_dock ( ) {
return scene_tree_dock ;
}
2018-05-17 08:01:47 +02:00
InspectorDock * EditorNode : : get_inspector_dock ( ) {
return inspector_dock ;
2014-02-10 02:10:30 +01:00
}
2019-05-08 04:35:23 +02:00
void EditorNode : : _inherit_request ( String p_file ) {
current_option = FILE_NEW_INHERITED_SCENE ;
_dialog_action ( p_file ) ;
}
2018-05-17 08:01:47 +02:00
void EditorNode : : _instance_request ( const Vector < String > & p_files ) {
request_instance_scenes ( p_files ) ;
2014-02-10 02:10:30 +01:00
}
void EditorNode : : _close_messages ( ) {
2015-06-14 03:12:53 +02:00
old_split_ofs = center_split - > get_split_offset ( ) ;
center_split - > set_split_offset ( 0 ) ;
2014-02-10 02:10:30 +01:00
}
void EditorNode : : _show_messages ( ) {
2015-06-14 03:12:53 +02:00
center_split - > set_split_offset ( old_split_ofs ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _add_to_recent_scenes ( const String & p_scene ) {
2018-01-09 13:42:45 +01:00
Array rc = EditorSettings : : get_singleton ( ) - > get_project_metadata ( " recent_files " , " scenes " , Array ( ) ) ;
2021-05-05 12:44:11 +02:00
if ( rc . find ( p_scene ) ! = - 1 ) {
2018-01-09 13:42:45 +01:00
rc . erase ( p_scene ) ;
2021-05-05 12:44:11 +02:00
}
2018-01-09 13:42:45 +01:00
rc . push_front ( p_scene ) ;
2021-05-05 12:44:11 +02:00
if ( rc . size ( ) > 10 ) {
2014-02-10 02:10:30 +01:00
rc . resize ( 10 ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2018-01-09 13:42:45 +01:00
EditorSettings : : get_singleton ( ) - > set_project_metadata ( " recent_files " , " scenes " , rc ) ;
2014-02-10 02:10:30 +01:00
_update_recent_scenes ( ) ;
}
void EditorNode : : _open_recent_scene ( int p_idx ) {
2017-10-12 04:35:15 +02:00
if ( p_idx = = recent_scenes - > get_item_count ( ) - 1 ) {
2018-01-09 13:42:45 +01:00
EditorSettings : : get_singleton ( ) - > set_project_metadata ( " recent_files " , " scenes " , Array ( ) ) ;
2017-10-12 04:35:15 +02:00
call_deferred ( " _update_recent_scenes " ) ;
} else {
2018-01-09 13:42:45 +01:00
Array rc = EditorSettings : : get_singleton ( ) - > get_project_metadata ( " recent_files " , " scenes " , Array ( ) ) ;
2017-10-12 04:35:15 +02:00
ERR_FAIL_INDEX ( p_idx , rc . size ( ) ) ;
2014-02-10 02:10:30 +01:00
2018-01-09 13:42:45 +01:00
if ( load_scene ( rc [ p_idx ] ) ! = OK ) {
rc . remove ( p_idx ) ;
EditorSettings : : get_singleton ( ) - > set_project_metadata ( " recent_files " , " scenes " , rc ) ;
_update_recent_scenes ( ) ;
}
2017-10-12 04:35:15 +02:00
}
2014-02-10 02:10:30 +01:00
}
void EditorNode : : _update_recent_scenes ( ) {
2018-01-09 13:42:45 +01:00
Array rc = EditorSettings : : get_singleton ( ) - > get_project_metadata ( " recent_files " , " scenes " , Array ( ) ) ;
2014-02-10 02:10:30 +01:00
recent_scenes - > clear ( ) ;
2017-10-12 04:35:15 +02:00
2018-01-09 13:42:45 +01:00
String path ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < rc . size ( ) ; i + + ) {
2018-01-09 13:42:45 +01:00
path = rc [ i ] ;
recent_scenes - > add_item ( path . replace ( " res:// " , " " ) , i ) ;
2014-02-10 02:10:30 +01:00
}
2017-10-12 04:35:15 +02:00
recent_scenes - > add_separator ( ) ;
recent_scenes - > add_shortcut ( ED_SHORTCUT ( " editor/clear_recent " , TTR ( " Clear Recent Scenes " ) ) ) ;
recent_scenes - > set_as_minsize ( ) ;
2014-02-10 02:10:30 +01:00
}
2016-01-08 12:27:34 +01:00
void EditorNode : : _quick_opened ( ) {
Vector < String > files = quick_open - > get_selected_files ( ) ;
2020-06-29 01:04:28 +02:00
bool open_scene_dialog = quick_open - > get_base_type ( ) = = " PackedScene " ;
2016-01-08 12:27:34 +01:00
for ( int i = 0 ; i < files . size ( ) ; i + + ) {
String res_path = files [ i ] ;
2014-02-10 02:10:30 +01:00
2020-06-29 01:04:28 +02:00
List < String > scene_extensions ;
ResourceLoader : : get_recognized_extensions_for_type ( " PackedScene " , & scene_extensions ) ;
2022-11-01 08:58:04 +01:00
if ( open_scene_dialog | | scene_extensions . find ( files [ i ] . get_extension ( ) . to_lower ( ) ) ) {
2016-01-08 12:27:34 +01:00
open_request ( res_path ) ;
} else {
load_resource ( res_path ) ;
}
}
2014-02-10 02:10:30 +01:00
}
2016-02-17 19:40:06 +01:00
void EditorNode : : _quick_run ( ) {
2017-03-05 16:44:50 +01:00
_run ( false , quick_run - > get_selected ( ) ) ;
2014-02-10 02:10:30 +01:00
}
void EditorNode : : notify_child_process_exited ( ) {
2017-03-05 16:44:50 +01:00
_menu_option_confirm ( RUN_STOP , false ) ;
2014-02-10 02:10:30 +01:00
stop_button - > set_pressed ( false ) ;
editor_run . stop ( ) ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : add_io_error ( const String & p_error ) {
_load_error_notify ( singleton , p_error ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _load_error_notify ( void * p_ud , const String & p_text ) {
EditorNode * en = ( EditorNode * ) p_ud ;
en - > load_errors - > add_image ( en - > gui_base - > get_icon ( " Error " , " EditorIcons " ) ) ;
en - > load_errors - > add_text ( p_text + " \n " ) ;
2014-02-10 02:10:30 +01:00
en - > load_error_dialog - > popup_centered_ratio ( 0.5 ) ;
}
2017-03-05 16:44:50 +01:00
bool EditorNode : : _find_scene_in_use ( Node * p_node , const String & p_path ) const {
if ( p_node - > get_filename ( ) = = p_path ) {
2014-06-19 07:23:03 +02:00
return true ;
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
if ( _find_scene_in_use ( p_node - > get_child ( i ) , p_path ) ) {
2014-06-19 07:23:03 +02:00
return true ;
}
}
return false ;
}
2017-03-05 16:44:50 +01:00
bool EditorNode : : is_scene_in_use ( const String & p_path ) {
2014-06-19 07:23:03 +02:00
Node * es = get_edited_scene ( ) ;
2021-05-05 12:44:11 +02:00
if ( es ) {
2017-03-05 16:44:50 +01:00
return _find_scene_in_use ( es , p_path ) ;
2021-05-05 12:44:11 +02:00
}
2014-06-19 07:23:03 +02:00
return false ;
}
2014-02-10 02:10:30 +01:00
void EditorNode : : register_editor_types ( ) {
2023-01-22 19:42:34 +01:00
OS : : get_singleton ( ) - > benchmark_begin_measure ( " register_editor_types " ) ;
2018-10-03 22:12:59 +02:00
ResourceLoader : : set_timestamp_on_load ( true ) ;
ResourceSaver : : set_timestamp_on_save ( true ) ;
2017-01-03 03:03:46 +01:00
ClassDB : : register_class < EditorPlugin > ( ) ;
2017-04-09 00:37:31 +02:00
ClassDB : : register_class < EditorImportPlugin > ( ) ;
2017-01-03 03:03:46 +01:00
ClassDB : : register_class < EditorScript > ( ) ;
ClassDB : : register_class < EditorSelection > ( ) ;
ClassDB : : register_class < EditorFileDialog > ( ) ;
2017-11-10 05:25:10 +01:00
ClassDB : : register_virtual_class < EditorSettings > ( ) ;
2017-01-03 03:03:46 +01:00
ClassDB : : register_class < EditorSpatialGizmo > ( ) ;
2018-10-29 11:30:28 +01:00
ClassDB : : register_class < EditorSpatialGizmoPlugin > ( ) ;
2017-11-10 05:25:10 +01:00
ClassDB : : register_virtual_class < EditorResourcePreview > ( ) ;
2017-01-03 03:03:46 +01:00
ClassDB : : register_class < EditorResourcePreviewGenerator > ( ) ;
2017-11-10 05:25:10 +01:00
ClassDB : : register_virtual_class < EditorFileSystem > ( ) ;
2017-01-03 03:03:46 +01:00
ClassDB : : register_class < EditorFileSystemDirectory > ( ) ;
2019-09-03 16:42:08 +02:00
ClassDB : : register_class < EditorVCSInterface > ( ) ;
2017-07-06 09:18:20 +02:00
ClassDB : : register_virtual_class < ScriptEditor > ( ) ;
2017-08-26 15:32:15 +02:00
ClassDB : : register_virtual_class < EditorInterface > ( ) ;
2017-09-15 00:38:38 +02:00
ClassDB : : register_class < EditorExportPlugin > ( ) ;
2017-09-22 14:20:28 +02:00
ClassDB : : register_class < EditorResourceConversionPlugin > ( ) ;
2017-12-07 19:44:20 +01:00
ClassDB : : register_class < EditorSceneImporter > ( ) ;
2018-05-15 22:12:35 +02:00
ClassDB : : register_class < EditorInspector > ( ) ;
ClassDB : : register_class < EditorInspectorPlugin > ( ) ;
ClassDB : : register_class < EditorProperty > ( ) ;
2018-06-07 17:46:14 +02:00
ClassDB : : register_class < AnimationTrackEditPlugin > ( ) ;
2018-06-30 05:08:28 +02:00
ClassDB : : register_class < ScriptCreateDialog > ( ) ;
2019-04-09 00:18:03 +02:00
ClassDB : : register_class < EditorFeatureProfile > ( ) ;
2019-10-20 17:43:14 +02:00
ClassDB : : register_class < EditorSpinSlider > ( ) ;
2021-06-10 18:07:48 +02:00
ClassDB : : register_class < EditorResourcePicker > ( ) ;
ClassDB : : register_class < EditorScriptPicker > ( ) ;
2020-03-17 01:40:15 +01:00
ClassDB : : register_virtual_class < FileSystemDock > ( ) ;
2017-12-07 19:44:20 +01:00
2017-08-26 17:46:49 +02:00
// FIXME: Is this stuff obsolete, or should it be ported to new APIs?
2017-11-19 15:45:16 +01:00
ClassDB : : register_class < EditorScenePostImport > ( ) ;
2017-08-26 17:46:49 +02:00
//ClassDB::register_type<EditorImportExport>();
2023-01-22 19:42:34 +01:00
OS : : get_singleton ( ) - > benchmark_end_measure ( " register_editor_types " ) ;
2014-02-10 02:10:30 +01:00
}
2014-02-25 13:31:47 +01:00
void EditorNode : : unregister_editor_types ( ) {
2023-01-22 19:42:34 +01:00
OS : : get_singleton ( ) - > benchmark_begin_measure ( " unregister_editor_types " ) ;
2014-02-25 13:31:47 +01:00
_init_callbacks . clear ( ) ;
2021-08-03 15:21:05 +02:00
EditorResourcePicker : : clear_caches ( ) ;
2023-01-22 19:42:34 +01:00
OS : : get_singleton ( ) - > benchmark_end_measure ( " unregister_editor_types " ) ;
2014-02-25 13:31:47 +01:00
}
2014-02-10 02:10:30 +01:00
void EditorNode : : stop_child_process ( ) {
2017-03-05 16:44:50 +01:00
_menu_option_confirm ( RUN_STOP , false ) ;
2014-02-10 02:10:30 +01:00
}
2019-07-19 21:21:30 +02:00
Ref < Script > EditorNode : : get_object_custom_type_base ( const Object * p_object ) const {
2021-05-04 16:00:45 +02:00
ERR_FAIL_COND_V ( ! p_object , nullptr ) ;
2019-07-19 21:21:30 +02:00
Ref < Script > script = p_object - > get_script ( ) ;
if ( script . is_valid ( ) ) {
// Uncommenting would break things! Consider adding a parameter if you need it.
// StringName name = EditorNode::get_editor_data().script_class_get_name(base_script->get_path());
// if (name != StringName())
// return name;
// should probably be deprecated in 4.x
StringName base = script - > get_instance_base_type ( ) ;
if ( base ! = StringName ( ) & & EditorNode : : get_editor_data ( ) . get_custom_types ( ) . has ( base ) ) {
const Vector < EditorData : : CustomType > & types = EditorNode : : get_editor_data ( ) . get_custom_types ( ) [ base ] ;
Ref < Script > base_script = script ;
while ( base_script . is_valid ( ) ) {
for ( int i = 0 ; i < types . size ( ) ; + + i ) {
if ( types [ i ] . script = = base_script ) {
return types [ i ] . script ;
}
}
base_script = base_script - > get_base_script ( ) ;
}
}
}
2021-05-04 16:00:45 +02:00
return nullptr ;
2019-07-19 21:21:30 +02:00
}
StringName EditorNode : : get_object_custom_type_name ( const Object * p_object ) const {
ERR_FAIL_COND_V ( ! p_object , StringName ( ) ) ;
Ref < Script > script = p_object - > get_script ( ) ;
if ( script . is_null ( ) & & p_object - > is_class ( " Script " ) ) {
script = p_object ;
}
if ( script . is_valid ( ) ) {
Ref < Script > base_script = script ;
while ( base_script . is_valid ( ) ) {
StringName name = EditorNode : : get_editor_data ( ) . script_class_get_name ( base_script - > get_path ( ) ) ;
2021-05-05 12:44:11 +02:00
if ( name ! = StringName ( ) ) {
2019-07-19 21:21:30 +02:00
return name ;
2021-05-05 12:44:11 +02:00
}
2019-07-19 21:21:30 +02:00
// should probably be deprecated in 4.x
StringName base = base_script - > get_instance_base_type ( ) ;
if ( base ! = StringName ( ) & & EditorNode : : get_editor_data ( ) . get_custom_types ( ) . has ( base ) ) {
const Vector < EditorData : : CustomType > & types = EditorNode : : get_editor_data ( ) . get_custom_types ( ) [ base ] ;
for ( int i = 0 ; i < types . size ( ) ; + + i ) {
if ( types [ i ] . script = = base_script ) {
return types [ i ] . name ;
}
}
}
base_script = base_script - > get_base_script ( ) ;
}
}
return StringName ( ) ;
}
2019-10-23 20:11:04 +02:00
Ref < ImageTexture > EditorNode : : _load_custom_class_icon ( const String & p_path ) const {
if ( p_path . length ( ) ) {
Ref < Image > img = memnew ( Image ) ;
Error err = ImageLoader : : load_image ( p_path , img ) ;
if ( err = = OK ) {
Ref < ImageTexture > icon = memnew ( ImageTexture ) ;
img - > resize ( 16 * EDSCALE , 16 * EDSCALE , Image : : INTERPOLATE_LANCZOS ) ;
icon - > create_from_image ( img ) ;
return icon ;
}
}
2021-05-04 16:00:45 +02:00
return nullptr ;
2019-10-23 20:11:04 +02:00
}
2021-02-24 18:29:58 +01:00
String EditorNode : : _to_absolute_plugin_path ( const String & p_plugin_name ) {
return " res://addons/ " + p_plugin_name + " /plugin.cfg " ;
}
2021-07-06 16:10:07 +02:00
void EditorNode : : _pick_main_scene_custom_action ( const String & p_custom_action_name ) {
if ( p_custom_action_name = = " select_current " ) {
Node * scene = editor_data . get_edited_scene_root ( ) ;
if ( ! scene ) {
show_accept ( TTR ( " There is no defined scene to run. " ) , TTR ( " OK " ) ) ;
return ;
}
pick_main_scene - > hide ( ) ;
current_option = SETTINGS_PICK_MAIN_SCENE ;
_dialog_action ( scene - > get_filename ( ) ) ;
}
}
2022-05-05 14:27:29 +02:00
Ref < Texture > EditorNode : : get_object_icon ( const Object * p_object , const String & p_fallback ) {
2021-05-04 16:00:45 +02:00
ERR_FAIL_COND_V ( ! p_object | | ! gui_base , nullptr ) ;
2018-09-02 23:40:51 +02:00
Ref < Script > script = p_object - > get_script ( ) ;
if ( script . is_null ( ) & & p_object - > is_class ( " Script " ) ) {
script = p_object ;
}
2022-05-05 14:27:29 +02:00
if ( script . is_valid ( ) & & ! script_icon_cache . has ( script ) ) {
2019-07-19 21:21:30 +02:00
Ref < Script > base_script = script ;
while ( base_script . is_valid ( ) ) {
StringName name = EditorNode : : get_editor_data ( ) . script_class_get_name ( base_script - > get_path ( ) ) ;
String icon_path = EditorNode : : get_editor_data ( ) . script_class_get_icon_path ( name ) ;
2019-10-23 20:11:04 +02:00
Ref < ImageTexture > icon = _load_custom_class_icon ( icon_path ) ;
if ( icon . is_valid ( ) ) {
2022-05-05 14:27:29 +02:00
script_icon_cache [ script ] = icon ;
2019-10-23 20:11:04 +02:00
return icon ;
}
2019-07-19 21:21:30 +02:00
// should probably be deprecated in 4.x
StringName base = base_script - > get_instance_base_type ( ) ;
if ( base ! = StringName ( ) & & EditorNode : : get_editor_data ( ) . get_custom_types ( ) . has ( base ) ) {
const Vector < EditorData : : CustomType > & types = EditorNode : : get_editor_data ( ) . get_custom_types ( ) [ base ] ;
for ( int i = 0 ; i < types . size ( ) ; + + i ) {
if ( types [ i ] . script = = base_script & & types [ i ] . icon . is_valid ( ) ) {
2022-05-05 14:27:29 +02:00
script_icon_cache [ script ] = types [ i ] . icon ;
2019-07-19 21:21:30 +02:00
return types [ i ] . icon ;
2018-11-11 05:46:20 +01:00
}
}
}
2019-07-19 21:21:30 +02:00
base_script = base_script - > get_base_script ( ) ;
2018-11-11 05:46:20 +01:00
}
2022-05-05 14:27:29 +02:00
// If no icon found, cache it as null.
script_icon_cache [ script ] = Ref < Texture > ( ) ;
} else if ( script . is_valid ( ) & & script_icon_cache . has ( script ) & & script_icon_cache [ script ] . is_valid ( ) ) {
return script_icon_cache [ script ] ;
2018-09-02 23:40:51 +02:00
}
2018-11-11 05:46:20 +01:00
// should probably be deprecated in 4.x
2021-05-05 12:44:11 +02:00
if ( p_object - > has_meta ( " _editor_icon " ) ) {
2018-09-02 23:40:51 +02:00
return p_object - > get_meta ( " _editor_icon " ) ;
2021-05-05 12:44:11 +02:00
}
2018-09-02 23:40:51 +02:00
2021-05-05 12:44:11 +02:00
if ( gui_base - > has_icon ( p_object - > get_class ( ) , " EditorIcons " ) ) {
2018-11-11 05:46:20 +01:00
return gui_base - > get_icon ( p_object - > get_class ( ) , " EditorIcons " ) ;
2021-05-05 12:44:11 +02:00
}
2018-09-02 23:40:51 +02:00
2021-05-05 12:44:11 +02:00
if ( p_fallback . length ( ) ) {
2018-09-02 23:40:51 +02:00
return gui_base - > get_icon ( p_fallback , " EditorIcons " ) ;
2021-05-05 12:44:11 +02:00
}
2018-09-02 23:40:51 +02:00
2021-05-04 16:00:45 +02:00
return nullptr ;
2018-09-02 23:40:51 +02:00
}
Ref < Texture > EditorNode : : get_class_icon ( const String & p_class , const String & p_fallback ) const {
2021-05-04 16:00:45 +02:00
ERR_FAIL_COND_V_MSG ( p_class . empty ( ) , nullptr , " Class name cannot be empty. " ) ;
2018-09-02 23:40:51 +02:00
if ( ScriptServer : : is_global_class ( p_class ) ) {
2022-04-26 17:29:02 +02:00
String class_name = p_class ;
Ref < Script > script = EditorNode : : get_editor_data ( ) . script_class_load_script ( class_name ) ;
while ( true ) {
String icon_path = EditorNode : : get_editor_data ( ) . script_class_get_icon_path ( class_name ) ;
Ref < Texture > icon = _load_custom_class_icon ( icon_path ) ;
2019-10-23 20:11:04 +02:00
if ( icon . is_valid ( ) ) {
2022-04-26 17:29:02 +02:00
return icon ; // Current global class has icon.
2019-02-07 00:53:24 +01:00
}
2022-04-26 17:29:02 +02:00
// Find next global class along the inheritance chain.
do {
Ref < Script > base_script = script - > get_base_script ( ) ;
if ( base_script . is_null ( ) ) {
// We've reached a native class, use its icon.
String base_type ;
script - > get_language ( ) - > get_global_class_name ( script - > get_path ( ) , & base_type ) ;
2022-04-29 03:40:20 +02:00
if ( gui_base - > has_icon ( base_type , " EditorIcons " ) ) {
return gui_base - > get_icon ( base_type , " EditorIcons " ) ;
}
return gui_base - > get_icon ( p_fallback , " EditorIcons " ) ;
2022-04-26 17:29:02 +02:00
}
script = base_script ;
class_name = EditorNode : : get_editor_data ( ) . script_class_get_name ( script - > get_path ( ) ) ;
} while ( class_name . empty ( ) ) ;
2019-02-07 00:53:24 +01:00
}
2018-09-02 23:40:51 +02:00
}
2021-05-04 14:20:36 +02:00
const Map < String , Vector < EditorData : : CustomType > > & p_map = EditorNode : : get_editor_data ( ) . get_custom_types ( ) ;
for ( const Map < String , Vector < EditorData : : CustomType > > : : Element * E = p_map . front ( ) ; E ; E = E - > next ( ) ) {
2018-09-02 23:40:51 +02:00
const Vector < EditorData : : CustomType > & ct = E - > value ( ) ;
for ( int i = 0 ; i < ct . size ( ) ; + + i ) {
if ( ct [ i ] . name = = p_class ) {
if ( ct [ i ] . icon . is_valid ( ) ) {
return ct [ i ] . icon ;
}
}
}
}
2020-06-25 01:13:13 +02:00
if ( gui_base - > has_icon ( p_class , " EditorIcons " ) ) {
return gui_base - > get_icon ( p_class , " EditorIcons " ) ;
}
if ( p_fallback . length ( ) & & gui_base - > has_icon ( p_fallback , " EditorIcons " ) ) {
2018-09-02 23:40:51 +02:00
return gui_base - > get_icon ( p_fallback , " EditorIcons " ) ;
2020-06-25 01:13:13 +02:00
}
2018-09-02 23:40:51 +02:00
2021-05-04 16:00:45 +02:00
return nullptr ;
2018-09-02 23:40:51 +02:00
}
2017-12-14 12:59:46 +01:00
void EditorNode : : progress_add_task ( const String & p_task , const String & p_label , int p_steps , bool p_can_cancel ) {
2020-01-14 11:32:15 +01:00
if ( singleton - > cmdline_export_mode ) {
2018-11-28 12:45:51 +01:00
print_line ( p_task + " : begin: " + p_label + " steps: " + itos ( p_steps ) ) ;
} else {
singleton - > progress_dialog - > add_task ( p_task , p_label , p_steps , p_can_cancel ) ;
}
2014-02-10 02:10:30 +01:00
}
2017-12-14 12:59:46 +01:00
bool EditorNode : : progress_task_step ( const String & p_task , const String & p_state , int p_step , bool p_force_refresh ) {
2020-01-14 11:32:15 +01:00
if ( singleton - > cmdline_export_mode ) {
2018-11-28 12:45:51 +01:00
print_line ( " \t " + p_task + " : step " + itos ( p_step ) + " : " + p_state ) ;
return false ;
} else {
return singleton - > progress_dialog - > task_step ( p_task , p_state , p_step , p_force_refresh ) ;
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void EditorNode : : progress_end_task ( const String & p_task ) {
2020-01-14 11:32:15 +01:00
if ( singleton - > cmdline_export_mode ) {
2018-11-28 12:45:51 +01:00
print_line ( p_task + " : end " ) ;
} else {
singleton - > progress_dialog - > end_task ( p_task ) ;
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void EditorNode : : progress_add_task_bg ( const String & p_task , const String & p_label , int p_steps ) {
singleton - > progress_hb - > add_task ( p_task , p_label , p_steps ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void EditorNode : : progress_task_step_bg ( const String & p_task , int p_step ) {
singleton - > progress_hb - > task_step ( p_task , p_step ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void EditorNode : : progress_end_task_bg ( const String & p_task ) {
2014-02-10 02:10:30 +01:00
singleton - > progress_hb - > end_task ( p_task ) ;
}
2017-03-05 16:44:50 +01:00
Ref < Texture > EditorNode : : _file_dialog_get_icon ( const String & p_path ) {
2017-01-14 15:07:57 +01:00
EditorFileSystemDirectory * efsd = EditorFileSystem : : get_singleton ( ) - > get_filesystem_path ( p_path . get_base_dir ( ) ) ;
2014-02-10 02:10:30 +01:00
if ( efsd ) {
String file = p_path . get_file ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < efsd - > get_file_count ( ) ; i + + ) {
if ( efsd - > get_file ( i ) = = file ) {
2014-02-10 02:10:30 +01:00
String type = efsd - > get_file_type ( i ) ;
if ( singleton - > icon_type_cache . has ( type ) ) {
return singleton - > icon_type_cache [ type ] ;
} else {
return singleton - > icon_type_cache [ " Object " ] ;
}
}
}
}
return singleton - > icon_type_cache [ " Object " ] ;
}
2018-02-25 17:04:16 +01:00
void EditorNode : : _build_icon_type_cache ( ) {
List < StringName > tl ;
StringName ei = " EditorIcons " ;
theme_base - > get_theme ( ) - > get_icon_list ( ei , & tl ) ;
for ( List < StringName > : : Element * E = tl . front ( ) ; E ; E = E - > next ( ) ) {
2021-05-05 12:44:11 +02:00
if ( ! ClassDB : : class_exists ( E - > get ( ) ) ) {
2018-02-25 17:04:16 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2018-02-25 17:04:16 +01:00
icon_type_cache [ E - > get ( ) ] = theme_base - > get_theme ( ) - > get_icon ( E - > get ( ) , ei ) ;
}
}
2014-02-10 02:10:30 +01:00
void EditorNode : : _file_dialog_register ( FileDialog * p_dialog ) {
singleton - > file_dialogs . insert ( p_dialog ) ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _file_dialog_unregister ( FileDialog * p_dialog ) {
2014-02-10 02:10:30 +01:00
singleton - > file_dialogs . erase ( p_dialog ) ;
}
2015-05-31 06:59:42 +02:00
void EditorNode : : _editor_file_dialog_register ( EditorFileDialog * p_dialog ) {
singleton - > editor_file_dialogs . insert ( p_dialog ) ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _editor_file_dialog_unregister ( EditorFileDialog * p_dialog ) {
2015-05-31 06:59:42 +02:00
singleton - > editor_file_dialogs . erase ( p_dialog ) ;
}
2014-02-25 13:31:47 +01:00
Vector < EditorNodeInitCallback > EditorNode : : _init_callbacks ;
2014-02-10 02:10:30 +01:00
2020-01-08 14:22:50 +01:00
Error EditorNode : : export_preset ( const String & p_preset , const String & p_path , bool p_debug , bool p_pack_only ) {
2017-09-14 19:49:11 +02:00
export_defer . preset = p_preset ;
2017-03-05 16:44:50 +01:00
export_defer . path = p_path ;
export_defer . debug = p_debug ;
2020-01-08 14:22:50 +01:00
export_defer . pack_only = p_pack_only ;
2020-01-14 11:32:15 +01:00
cmdline_export_mode = true ;
2014-02-10 02:10:30 +01:00
return OK ;
}
2018-05-27 04:41:19 +02:00
void EditorNode : : show_accept ( const String & p_text , const String & p_title ) {
current_option = - 1 ;
accept - > get_ok ( ) - > set_text ( p_title ) ;
accept - > set_text ( p_text ) ;
accept - > popup_centered_minsize ( ) ;
}
2021-09-11 03:35:13 +02:00
void EditorNode : : show_save_accept ( const String & p_text , const String & p_title ) {
current_option = - 1 ;
save_accept - > get_ok ( ) - > set_text ( p_title ) ;
save_accept - > set_text ( p_text ) ;
save_accept - > popup_centered ( ) ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : show_warning ( const String & p_text , const String & p_title ) {
2019-08-21 09:04:55 +02:00
if ( warning - > is_inside_tree ( ) ) {
warning - > set_text ( p_text ) ;
warning - > set_title ( p_title ) ;
warning - > popup_centered_minsize ( ) ;
} else {
2021-06-18 13:26:58 +02:00
WARN_PRINT ( p_title + " " + p_text ) ;
2019-08-21 09:04:55 +02:00
}
2015-02-14 16:09:52 +01:00
}
2014-02-10 02:10:30 +01:00
2019-07-09 20:11:31 +02:00
void EditorNode : : _copy_warning ( const String & p_str ) {
OS : : get_singleton ( ) - > set_clipboard ( warning - > get_text ( ) ) ;
}
2017-05-20 17:38:03 +02:00
void EditorNode : : _dock_select_input ( const Ref < InputEvent > & p_input ) {
Ref < InputEventMouse > me = p_input ;
2015-06-14 03:12:53 +02:00
2017-05-20 17:38:03 +02:00
if ( me . is_valid ( ) ) {
2017-06-03 10:54:24 +02:00
Vector2 point = me - > get_position ( ) ;
2015-06-14 03:12:53 +02:00
int nrect = - 1 ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < DOCK_SLOT_MAX ; i + + ) {
2015-06-14 03:12:53 +02:00
if ( dock_select_rect [ i ] . has_point ( point ) ) {
2017-03-05 16:44:50 +01:00
nrect = i ;
2015-06-14 03:12:53 +02:00
break ;
}
}
2015-06-14 05:41:08 +02:00
2017-03-05 16:44:50 +01:00
if ( nrect ! = dock_select_rect_over ) {
2015-06-14 03:12:53 +02:00
dock_select - > update ( ) ;
2017-03-05 16:44:50 +01:00
dock_select_rect_over = nrect ;
2015-06-14 03:12:53 +02:00
}
2021-05-05 12:44:11 +02:00
if ( nrect = = - 1 ) {
2015-06-14 05:41:08 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2015-06-14 05:41:08 +02:00
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseButton > mb = me ;
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = 1 & & mb - > is_pressed ( ) & & dock_popup_selected ! = nrect ) {
2015-06-14 03:12:53 +02:00
Control * dock = dock_slot [ dock_popup_selected ] - > get_current_tab_control ( ) ;
if ( dock ) {
dock_slot [ dock_popup_selected ] - > remove_child ( dock ) ;
}
2017-03-05 16:44:50 +01:00
if ( dock_slot [ dock_popup_selected ] - > get_tab_count ( ) = = 0 ) {
2015-06-14 03:12:53 +02:00
dock_slot [ dock_popup_selected ] - > hide ( ) ;
2017-03-05 16:44:50 +01:00
} else {
2015-06-14 06:09:58 +02:00
dock_slot [ dock_popup_selected ] - > set_current_tab ( 0 ) ;
2015-06-14 03:12:53 +02:00
}
2015-06-14 06:09:58 +02:00
2015-06-14 03:12:53 +02:00
dock_slot [ nrect ] - > add_child ( dock ) ;
2017-03-05 16:44:50 +01:00
dock_popup_selected = nrect ;
dock_slot [ nrect ] - > set_current_tab ( dock_slot [ nrect ] - > get_tab_count ( ) - 1 ) ;
2015-06-14 03:12:53 +02:00
dock_slot [ nrect ] - > show ( ) ;
dock_select - > update ( ) ;
2018-09-14 16:56:18 +02:00
for ( int i = 0 ; i < vsplits . size ( ) ; i + + ) {
2017-03-05 16:44:50 +01:00
bool in_use = dock_slot [ i * 2 + 0 ] - > get_tab_count ( ) | | dock_slot [ i * 2 + 1 ] - > get_tab_count ( ) ;
2021-05-05 12:44:11 +02:00
if ( in_use ) {
2018-09-14 16:56:18 +02:00
vsplits [ i ] - > show ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2018-09-14 16:56:18 +02:00
vsplits [ i ] - > hide ( ) ;
2021-05-05 12:44:11 +02:00
}
2015-06-14 03:12:53 +02:00
}
2021-05-05 12:44:11 +02:00
if ( right_l_vsplit - > is_visible ( ) | | right_r_vsplit - > is_visible ( ) ) {
2017-12-22 19:49:14 +01:00
right_hsplit - > show ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-12-22 19:49:14 +01:00
right_hsplit - > hide ( ) ;
2021-05-05 12:44:11 +02:00
}
2017-12-22 19:49:14 +01:00
2017-08-19 00:51:17 +02:00
_edit_current ( ) ;
2015-06-14 03:12:53 +02:00
_save_docks ( ) ;
}
}
}
2015-06-14 05:41:08 +02:00
void EditorNode : : _dock_popup_exit ( ) {
2017-03-05 16:44:50 +01:00
dock_select_rect_over = - 1 ;
2015-06-14 05:41:08 +02:00
dock_select - > update ( ) ;
}
2015-06-14 03:12:53 +02:00
void EditorNode : : _dock_pre_popup ( int p_which ) {
2017-03-05 16:44:50 +01:00
dock_popup_selected = p_which ;
2015-06-14 03:12:53 +02:00
}
2015-06-14 05:41:08 +02:00
void EditorNode : : _dock_move_left ( ) {
2021-05-05 12:44:11 +02:00
if ( dock_popup_selected < 0 | | dock_popup_selected > = DOCK_SLOT_MAX ) {
2015-06-14 05:41:08 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
Control * current = dock_slot [ dock_popup_selected ] - > get_tab_control ( dock_slot [ dock_popup_selected ] - > get_current_tab ( ) ) ;
Control * prev = dock_slot [ dock_popup_selected ] - > get_tab_control ( dock_slot [ dock_popup_selected ] - > get_current_tab ( ) - 1 ) ;
2021-05-05 12:44:11 +02:00
if ( ! current | | ! prev ) {
2015-06-14 05:41:08 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
dock_slot [ dock_popup_selected ] - > move_child ( current , prev - > get_index ( ) ) ;
dock_slot [ dock_popup_selected ] - > set_current_tab ( dock_slot [ dock_popup_selected ] - > get_current_tab ( ) - 1 ) ;
2015-06-14 05:41:08 +02:00
dock_select - > update ( ) ;
2017-08-19 00:51:17 +02:00
_edit_current ( ) ;
2015-06-14 05:41:08 +02:00
_save_docks ( ) ;
}
void EditorNode : : _dock_move_right ( ) {
2017-03-05 16:44:50 +01:00
Control * current = dock_slot [ dock_popup_selected ] - > get_tab_control ( dock_slot [ dock_popup_selected ] - > get_current_tab ( ) ) ;
Control * next = dock_slot [ dock_popup_selected ] - > get_tab_control ( dock_slot [ dock_popup_selected ] - > get_current_tab ( ) + 1 ) ;
2021-05-05 12:44:11 +02:00
if ( ! current | | ! next ) {
2015-06-14 05:41:08 +02:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
dock_slot [ dock_popup_selected ] - > move_child ( next , current - > get_index ( ) ) ;
dock_slot [ dock_popup_selected ] - > set_current_tab ( dock_slot [ dock_popup_selected ] - > get_current_tab ( ) + 1 ) ;
2015-06-14 05:41:08 +02:00
dock_select - > update ( ) ;
2017-08-19 00:51:17 +02:00
_edit_current ( ) ;
2015-06-14 05:41:08 +02:00
_save_docks ( ) ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _dock_select_draw ( ) {
2015-06-14 03:12:53 +02:00
Size2 s = dock_select - > get_size ( ) ;
2017-03-05 16:44:50 +01:00
s . y / = 2.0 ;
s . x / = 6.0 ;
2015-06-14 03:12:53 +02:00
2017-03-05 16:44:50 +01:00
Color used = Color ( 0.6 , 0.6 , 0.6 , 0.8 ) ;
Color used_selected = Color ( 0.8 , 0.8 , 0.8 , 0.8 ) ;
2017-09-26 04:43:20 +02:00
Color tab_selected = theme_base - > get_color ( " mono_color " , " Editor " ) ;
2017-03-05 16:44:50 +01:00
Color unused = used ;
unused . a = 0.4 ;
Color unusable = unused ;
unusable . a = 0.1 ;
2015-06-14 03:12:53 +02:00
2017-03-05 16:44:50 +01:00
Rect2 unr ( s . x * 2 , 0 , s . x * 2 , s . y * 2 ) ;
2017-06-04 00:25:13 +02:00
unr . position + = Vector2 ( 2 , 5 ) ;
2017-03-05 16:44:50 +01:00
unr . size - = Vector2 ( 4 , 7 ) ;
2015-06-14 03:12:53 +02:00
2017-03-05 16:44:50 +01:00
dock_select - > draw_rect ( unr , unusable ) ;
2015-06-14 03:12:53 +02:00
dock_tab_move_left - > set_disabled ( true ) ;
dock_tab_move_right - > set_disabled ( true ) ;
2017-03-05 16:44:50 +01:00
if ( dock_popup_selected ! = - 1 & & dock_slot [ dock_popup_selected ] - > get_tab_count ( ) ) {
dock_tab_move_left - > set_disabled ( dock_slot [ dock_popup_selected ] - > get_current_tab ( ) = = 0 ) ;
dock_tab_move_right - > set_disabled ( dock_slot [ dock_popup_selected ] - > get_current_tab ( ) > = dock_slot [ dock_popup_selected ] - > get_tab_count ( ) - 1 ) ;
2015-06-14 03:12:53 +02:00
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < DOCK_SLOT_MAX ; i + + ) {
2015-06-14 03:12:53 +02:00
Vector2 ofs ;
2017-03-05 16:44:50 +01:00
switch ( i ) {
2015-06-14 03:12:53 +02:00
case DOCK_SLOT_LEFT_UL : {
} break ;
case DOCK_SLOT_LEFT_BL : {
2017-03-05 16:44:50 +01:00
ofs . y + = s . y ;
2015-06-14 03:12:53 +02:00
} break ;
case DOCK_SLOT_LEFT_UR : {
2017-03-05 16:44:50 +01:00
ofs . x + = s . x ;
2015-06-14 03:12:53 +02:00
} break ;
case DOCK_SLOT_LEFT_BR : {
2017-03-05 16:44:50 +01:00
ofs + = s ;
2015-06-14 03:12:53 +02:00
} break ;
case DOCK_SLOT_RIGHT_UL : {
2017-03-05 16:44:50 +01:00
ofs . x + = s . x * 4 ;
2015-06-14 03:12:53 +02:00
} break ;
case DOCK_SLOT_RIGHT_BL : {
2017-03-05 16:44:50 +01:00
ofs . x + = s . x * 4 ;
ofs . y + = s . y ;
2015-06-14 03:12:53 +02:00
} break ;
case DOCK_SLOT_RIGHT_UR : {
2017-03-05 16:44:50 +01:00
ofs . x + = s . x * 4 ;
ofs . x + = s . x ;
2015-06-14 03:12:53 +02:00
} break ;
case DOCK_SLOT_RIGHT_BR : {
2017-03-05 16:44:50 +01:00
ofs . x + = s . x * 4 ;
ofs + = s ;
2015-06-14 03:12:53 +02:00
} break ;
}
2017-03-05 16:44:50 +01:00
Rect2 r ( ofs , s ) ;
dock_select_rect [ i ] = r ;
2017-06-04 00:25:13 +02:00
r . position + = Vector2 ( 2 , 5 ) ;
2017-03-05 16:44:50 +01:00
r . size - = Vector2 ( 4 , 7 ) ;
2015-06-14 03:12:53 +02:00
2017-03-05 16:44:50 +01:00
if ( i = = dock_select_rect_over ) {
dock_select - > draw_rect ( r , used_selected ) ;
} else if ( dock_slot [ i ] - > get_child_count ( ) = = 0 ) {
dock_select - > draw_rect ( r , unused ) ;
2015-06-14 03:12:53 +02:00
} else {
2017-03-05 16:44:50 +01:00
dock_select - > draw_rect ( r , used ) ;
2015-06-14 03:12:53 +02:00
}
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < MIN ( 3 , dock_slot [ i ] - > get_child_count ( ) ) ; j + + ) {
int xofs = ( r . size . width / 3 ) * j ;
2015-06-14 03:12:53 +02:00
Color c = used ;
2021-05-05 12:44:11 +02:00
if ( i = = dock_popup_selected & & ( dock_slot [ i ] - > get_current_tab ( ) > 3 | | dock_slot [ i ] - > get_current_tab ( ) = = j ) ) {
2017-03-05 16:44:50 +01:00
c = tab_selected ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
dock_select - > draw_rect ( Rect2 ( 2 + ofs . x + xofs , ofs . y , r . size . width / 3 - 1 , 3 ) , c ) ;
2015-06-14 03:12:53 +02:00
}
}
}
void EditorNode : : _save_docks ( ) {
2019-02-27 22:14:24 +01:00
if ( waiting_for_first_scan ) {
return ; //scanning, do not touch docks
}
2015-06-14 03:12:53 +02:00
Ref < ConfigFile > config ;
config . instance ( ) ;
2015-11-22 19:11:17 +01:00
_save_docks_to_config ( config , " docks " ) ;
2017-11-25 00:32:54 +01:00
_save_open_scenes_to_config ( config , " EditorNode " ) ;
2015-11-22 19:11:17 +01:00
editor_data . get_plugin_window_layout ( config ) ;
2017-11-17 15:50:18 +01:00
config - > save ( EditorSettings : : get_singleton ( ) - > get_project_settings_dir ( ) . plus_file ( " editor_layout.cfg " ) ) ;
2015-11-22 19:11:17 +01:00
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _save_docks_to_config ( Ref < ConfigFile > p_layout , const String & p_section ) {
for ( int i = 0 ; i < DOCK_SLOT_MAX ; i + + ) {
2015-06-14 03:12:53 +02:00
String names ;
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < dock_slot [ i ] - > get_tab_count ( ) ; j + + ) {
2015-06-14 03:12:53 +02:00
String name = dock_slot [ i ] - > get_tab_control ( j ) - > get_name ( ) ;
2021-05-05 12:44:11 +02:00
if ( names ! = " " ) {
2017-03-05 16:44:50 +01:00
names + = " , " ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
names + = name ;
2015-06-14 03:12:53 +02:00
}
2017-03-05 16:44:50 +01:00
if ( names ! = " " ) {
p_layout - > set_value ( p_section , " dock_ " + itos ( i + 1 ) , names ) ;
2015-06-14 03:12:53 +02:00
}
}
2017-03-05 16:44:50 +01:00
p_layout - > set_value ( p_section , " dock_filesystem_split " , filesystem_dock - > get_split_offset ( ) ) ;
2019-02-25 23:39:49 +01:00
p_layout - > set_value ( p_section , " dock_filesystem_display_mode " , filesystem_dock - > get_display_mode ( ) ) ;
p_layout - > set_value ( p_section , " dock_filesystem_file_list_display_mode " , filesystem_dock - > get_file_list_display_mode ( ) ) ;
2017-01-25 02:46:44 +01:00
2018-09-14 16:56:18 +02:00
for ( int i = 0 ; i < vsplits . size ( ) ; i + + ) {
if ( vsplits [ i ] - > is_visible_in_tree ( ) ) {
p_layout - > set_value ( p_section , " dock_split_ " + itos ( i + 1 ) , vsplits [ i ] - > get_split_offset ( ) ) ;
2015-06-14 03:12:53 +02:00
}
}
2018-09-14 16:56:18 +02:00
for ( int i = 0 ; i < hsplits . size ( ) ; i + + ) {
p_layout - > set_value ( p_section , " dock_hsplit_ " + itos ( i + 1 ) , hsplits [ i ] - > get_split_offset ( ) ) ;
2015-06-22 05:03:19 +02:00
}
2015-06-14 03:12:53 +02:00
}
2017-11-25 00:32:54 +01:00
void EditorNode : : _save_open_scenes_to_config ( Ref < ConfigFile > p_layout , const String & p_section ) {
Array scenes ;
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
String path = editor_data . get_scene_path ( i ) ;
if ( path = = " " ) {
continue ;
}
scenes . push_back ( path ) ;
}
p_layout - > set_value ( p_section , " open_scenes " , scenes ) ;
}
2015-06-22 05:03:19 +02:00
void EditorNode : : save_layout ( ) {
dock_drag_timer - > start ( ) ;
}
2015-06-14 03:12:53 +02:00
void EditorNode : : _dock_split_dragged ( int ofs ) {
dock_drag_timer - > start ( ) ;
}
void EditorNode : : _load_docks ( ) {
Ref < ConfigFile > config ;
config . instance ( ) ;
2017-11-17 15:50:18 +01:00
Error err = config - > load ( EditorSettings : : get_singleton ( ) - > get_project_settings_dir ( ) . plus_file ( " editor_layout.cfg " ) ) ;
2017-03-05 16:44:50 +01:00
if ( err ! = OK ) {
2016-01-11 22:23:45 +01:00
//no config
2017-03-05 16:44:50 +01:00
if ( overridden_default_layout > = 0 ) {
2016-01-11 22:23:45 +01:00
_layout_menu_option ( overridden_default_layout ) ;
}
return ;
2015-06-14 03:12:53 +02:00
}
2015-11-22 19:11:17 +01:00
_load_docks_from_config ( config , " docks " ) ;
2017-11-25 00:32:54 +01:00
_load_open_scenes_from_config ( config , " EditorNode " ) ;
2018-09-21 05:14:04 +02:00
2015-11-22 19:11:17 +01:00
editor_data . set_plugin_window_layout ( config ) ;
}
2022-11-03 13:02:11 +01:00
void EditorNode : : _update_dock_slots_visibility ( bool p_keep_selected_tabs ) {
2016-05-30 20:29:43 +02:00
if ( ! docks_visible ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < DOCK_SLOT_MAX ; i + + ) {
2016-02-28 03:10:44 +01:00
dock_slot [ i ] - > hide ( ) ;
2016-05-30 20:29:43 +02:00
}
2016-02-28 03:10:44 +01:00
2018-09-14 16:56:18 +02:00
for ( int i = 0 ; i < vsplits . size ( ) ; i + + ) {
vsplits [ i ] - > hide ( ) ;
2016-05-30 20:29:43 +02:00
}
2016-02-28 03:10:44 +01:00
2016-05-30 20:29:43 +02:00
right_hsplit - > hide ( ) ;
} else {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < DOCK_SLOT_MAX ; i + + ) {
2019-04-09 00:18:03 +02:00
int tabs_visible = 0 ;
for ( int j = 0 ; j < dock_slot [ i ] - > get_tab_count ( ) ; j + + ) {
if ( ! dock_slot [ i ] - > get_tab_hidden ( j ) ) {
tabs_visible + + ;
}
}
2021-05-05 12:44:11 +02:00
if ( tabs_visible ) {
2016-05-30 20:29:43 +02:00
dock_slot [ i ] - > show ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2016-05-30 20:29:43 +02:00
dock_slot [ i ] - > hide ( ) ;
2021-05-05 12:44:11 +02:00
}
2016-05-30 20:29:43 +02:00
}
2016-02-28 03:10:44 +01:00
2018-09-14 16:56:18 +02:00
for ( int i = 0 ; i < vsplits . size ( ) ; i + + ) {
2017-03-05 16:44:50 +01:00
bool in_use = dock_slot [ i * 2 + 0 ] - > get_tab_count ( ) | | dock_slot [ i * 2 + 1 ] - > get_tab_count ( ) ;
2021-05-05 12:44:11 +02:00
if ( in_use ) {
2018-09-14 16:56:18 +02:00
vsplits [ i ] - > show ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2018-09-14 16:56:18 +02:00
vsplits [ i ] - > hide ( ) ;
2021-05-05 12:44:11 +02:00
}
2016-05-30 20:29:43 +02:00
}
2022-11-03 13:02:11 +01:00
if ( ! p_keep_selected_tabs ) {
for ( int i = 0 ; i < DOCK_SLOT_MAX ; i + + ) {
if ( dock_slot [ i ] - > is_visible ( ) & & dock_slot [ i ] - > get_tab_count ( ) ) {
dock_slot [ i ] - > set_current_tab ( 0 ) ;
}
2016-05-30 20:29:43 +02:00
}
2016-02-28 03:10:44 +01:00
}
2017-12-22 19:49:14 +01:00
2021-05-05 12:44:11 +02:00
if ( right_l_vsplit - > is_visible ( ) | | right_r_vsplit - > is_visible ( ) ) {
2017-12-22 19:49:14 +01:00
right_hsplit - > show ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-12-22 19:49:14 +01:00
right_hsplit - > hide ( ) ;
2021-05-05 12:44:11 +02:00
}
2016-02-28 03:10:44 +01:00
}
}
2018-02-07 14:01:45 +01:00
void EditorNode : : _dock_tab_changed ( int p_tab ) {
2018-09-13 03:38:39 +02:00
// update visibility but don't set current tab
2018-02-07 14:01:45 +01:00
if ( ! docks_visible ) {
for ( int i = 0 ; i < DOCK_SLOT_MAX ; i + + ) {
dock_slot [ i ] - > hide ( ) ;
}
2018-09-14 16:56:18 +02:00
for ( int i = 0 ; i < vsplits . size ( ) ; i + + ) {
vsplits [ i ] - > hide ( ) ;
2018-02-07 14:01:45 +01:00
}
right_hsplit - > hide ( ) ;
bottom_panel - > hide ( ) ;
} else {
for ( int i = 0 ; i < DOCK_SLOT_MAX ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( dock_slot [ i ] - > get_tab_count ( ) ) {
2018-02-07 14:01:45 +01:00
dock_slot [ i ] - > show ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2018-02-07 14:01:45 +01:00
dock_slot [ i ] - > hide ( ) ;
2021-05-05 12:44:11 +02:00
}
2018-02-07 14:01:45 +01:00
}
2018-09-14 16:56:18 +02:00
for ( int i = 0 ; i < vsplits . size ( ) ; i + + ) {
2018-02-07 14:01:45 +01:00
bool in_use = dock_slot [ i * 2 + 0 ] - > get_tab_count ( ) | | dock_slot [ i * 2 + 1 ] - > get_tab_count ( ) ;
2021-05-05 12:44:11 +02:00
if ( in_use ) {
2018-09-14 16:56:18 +02:00
vsplits [ i ] - > show ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2018-09-14 16:56:18 +02:00
vsplits [ i ] - > hide ( ) ;
2021-05-05 12:44:11 +02:00
}
2018-02-07 14:01:45 +01:00
}
bottom_panel - > show ( ) ;
2021-05-05 12:44:11 +02:00
if ( right_l_vsplit - > is_visible ( ) | | right_r_vsplit - > is_visible ( ) ) {
2018-02-07 14:01:45 +01:00
right_hsplit - > show ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2018-02-07 14:01:45 +01:00
right_hsplit - > hide ( ) ;
2021-05-05 12:44:11 +02:00
}
2018-02-07 14:01:45 +01:00
}
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _load_docks_from_config ( Ref < ConfigFile > p_layout , const String & p_section ) {
for ( int i = 0 ; i < DOCK_SLOT_MAX ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( ! p_layout - > has_section_key ( p_section , " dock_ " + itos ( i + 1 ) ) ) {
2015-06-14 03:12:53 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-06-14 03:12:53 +02:00
2017-03-05 16:44:50 +01:00
Vector < String > names = String ( p_layout - > get_value ( p_section , " dock_ " + itos ( i + 1 ) ) ) . split ( " , " ) ;
2015-06-14 03:12:53 +02:00
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < names . size ( ) ; j + + ) {
String name = names [ j ] ;
2015-06-14 03:12:53 +02:00
//find it, in a horribly inefficient way
2017-03-05 16:44:50 +01:00
int atidx = - 1 ;
2021-05-04 16:00:45 +02:00
Control * node = nullptr ;
2017-03-05 16:44:50 +01:00
for ( int k = 0 ; k < DOCK_SLOT_MAX ; k + + ) {
2021-05-05 12:44:11 +02:00
if ( ! dock_slot [ k ] - > has_node ( name ) ) {
2015-06-14 03:12:53 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2017-08-24 22:58:51 +02:00
node = Object : : cast_to < Control > ( dock_slot [ k ] - > get_node ( name ) ) ;
2021-05-05 12:44:11 +02:00
if ( ! node ) {
2015-06-14 03:12:53 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
atidx = k ;
2015-06-14 03:12:53 +02:00
break ;
}
2021-05-05 12:44:11 +02:00
if ( atidx = = - 1 ) { //well, it's not anywhere
2015-06-14 03:12:53 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-06-14 03:12:53 +02:00
2017-03-05 16:44:50 +01:00
if ( atidx = = i ) {
2015-06-14 03:12:53 +02:00
node - > raise ( ) ;
continue ;
}
dock_slot [ atidx ] - > remove_child ( node ) ;
2017-03-05 16:44:50 +01:00
if ( dock_slot [ atidx ] - > get_tab_count ( ) = = 0 ) {
2015-06-14 03:12:53 +02:00
dock_slot [ atidx ] - > hide ( ) ;
}
dock_slot [ i ] - > add_child ( node ) ;
dock_slot [ i ] - > show ( ) ;
}
}
2017-03-05 16:44:50 +01:00
if ( p_layout - > has_section_key ( p_section , " dock_filesystem_split " ) ) {
2019-02-27 21:36:12 +01:00
int fs_split_ofs = p_layout - > get_value ( p_section , " dock_filesystem_split " ) ;
2019-02-25 23:39:49 +01:00
filesystem_dock - > set_split_offset ( fs_split_ofs ) ;
}
if ( p_layout - > has_section_key ( p_section , " dock_filesystem_display_mode " ) ) {
FileSystemDock : : DisplayMode dock_filesystem_display_mode = FileSystemDock : : DisplayMode ( int ( p_layout - > get_value ( p_section , " dock_filesystem_display_mode " ) ) ) ;
filesystem_dock - > set_display_mode ( dock_filesystem_display_mode ) ;
}
if ( p_layout - > has_section_key ( p_section , " dock_filesystem_file_list_display_mode " ) ) {
FileSystemDock : : FileListDisplayMode dock_filesystem_file_list_display_mode = FileSystemDock : : FileListDisplayMode ( int ( p_layout - > get_value ( p_section , " dock_filesystem_file_list_display_mode " ) ) ) ;
filesystem_dock - > set_file_list_display_mode ( dock_filesystem_file_list_display_mode ) ;
2017-01-25 02:46:44 +01:00
}
2018-09-14 16:56:18 +02:00
for ( int i = 0 ; i < vsplits . size ( ) ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( ! p_layout - > has_section_key ( p_section , " dock_split_ " + itos ( i + 1 ) ) ) {
2015-06-14 03:12:53 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2015-06-14 03:12:53 +02:00
2017-03-05 16:44:50 +01:00
int ofs = p_layout - > get_value ( p_section , " dock_split_ " + itos ( i + 1 ) ) ;
2018-09-14 16:56:18 +02:00
vsplits [ i ] - > set_split_offset ( ofs ) ;
2015-06-14 03:12:53 +02:00
}
2018-09-14 16:56:18 +02:00
for ( int i = 0 ; i < hsplits . size ( ) ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( ! p_layout - > has_section_key ( p_section , " dock_hsplit_ " + itos ( i + 1 ) ) ) {
2015-06-22 05:03:19 +02:00
continue ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
int ofs = p_layout - > get_value ( p_section , " dock_hsplit_ " + itos ( i + 1 ) ) ;
2018-09-14 16:56:18 +02:00
hsplits [ i ] - > set_split_offset ( ofs ) ;
2015-06-22 05:03:19 +02:00
}
2018-09-14 16:56:18 +02:00
for ( int i = 0 ; i < vsplits . size ( ) ; i + + ) {
2017-03-05 16:44:50 +01:00
bool in_use = dock_slot [ i * 2 + 0 ] - > get_tab_count ( ) | | dock_slot [ i * 2 + 1 ] - > get_tab_count ( ) ;
2021-05-05 12:44:11 +02:00
if ( in_use ) {
2018-09-14 16:56:18 +02:00
vsplits [ i ] - > show ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2018-09-14 16:56:18 +02:00
vsplits [ i ] - > hide ( ) ;
2021-05-05 12:44:11 +02:00
}
2015-06-14 03:12:53 +02:00
}
2015-06-14 05:41:08 +02:00
2021-05-05 12:44:11 +02:00
if ( right_l_vsplit - > is_visible ( ) | | right_r_vsplit - > is_visible ( ) ) {
2017-12-22 19:49:14 +01:00
right_hsplit - > show ( ) ;
2021-05-05 12:44:11 +02:00
} else {
2017-12-22 19:49:14 +01:00
right_hsplit - > hide ( ) ;
2021-05-05 12:44:11 +02:00
}
2017-12-22 19:49:14 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < DOCK_SLOT_MAX ; i + + ) {
2017-01-13 14:45:50 +01:00
if ( dock_slot [ i ] - > is_visible ( ) & & dock_slot [ i ] - > get_tab_count ( ) ) {
2015-06-14 05:41:08 +02:00
dock_slot [ i ] - > set_current_tab ( 0 ) ;
}
}
2015-11-22 19:11:17 +01:00
}
2015-06-14 05:41:08 +02:00
2017-11-25 00:32:54 +01:00
void EditorNode : : _load_open_scenes_from_config ( Ref < ConfigFile > p_layout , const String & p_section ) {
2018-05-17 23:02:16 +02:00
if ( ! bool ( EDITOR_GET ( " interface/scene_tabs/restore_scenes_on_load " ) ) ) {
2017-11-25 00:32:54 +01:00
return ;
}
if ( ! p_layout - > has_section ( p_section ) | | ! p_layout - > has_section_key ( p_section , " open_scenes " ) ) {
return ;
}
restoring_scenes = true ;
Array scenes = p_layout - > get_value ( p_section , " open_scenes " ) ;
for ( int i = 0 ; i < scenes . size ( ) ; i + + ) {
load_scene ( scenes [ i ] ) ;
}
2019-04-15 22:17:49 +02:00
save_layout ( ) ;
2017-11-25 00:32:54 +01:00
restoring_scenes = false ;
}
2018-09-21 05:14:04 +02:00
bool EditorNode : : has_scenes_in_session ( ) {
if ( ! bool ( EDITOR_GET ( " interface/scene_tabs/restore_scenes_on_load " ) ) ) {
return false ;
}
Ref < ConfigFile > config ;
config . instance ( ) ;
Error err = config - > load ( EditorSettings : : get_singleton ( ) - > get_project_settings_dir ( ) . plus_file ( " editor_layout.cfg " ) ) ;
if ( err ! = OK ) {
return false ;
}
if ( ! config - > has_section ( " EditorNode " ) | | ! config - > has_section_key ( " EditorNode " , " open_scenes " ) ) {
return false ;
}
Array scenes = config - > get_value ( " EditorNode " , " open_scenes " ) ;
return ! scenes . empty ( ) ;
}
2019-03-22 02:08:28 +01:00
bool EditorNode : : ensure_main_scene ( bool p_from_native ) {
pick_main_scene - > set_meta ( " from_native " , p_from_native ) ; //whether from play button or native run
String main_scene = GLOBAL_DEF ( " application/run/main_scene " , " " ) ;
if ( main_scene = = " " ) {
current_option = - 1 ;
pick_main_scene - > set_text ( TTR ( " No main scene has ever been defined, select one? \n You can change it later in \" Project Settings \" under the 'application' category. " ) ) ;
pick_main_scene - > popup_centered_minsize ( ) ;
2021-07-06 16:10:07 +02:00
if ( editor_data . get_edited_scene_root ( ) ) {
select_current_scene_button - > set_disabled ( false ) ;
select_current_scene_button - > grab_focus ( ) ;
} else {
select_current_scene_button - > set_disabled ( true ) ;
}
2019-03-22 02:08:28 +01:00
return false ;
}
if ( ! FileAccess : : exists ( main_scene ) ) {
current_option = - 1 ;
pick_main_scene - > set_text ( vformat ( TTR ( " Selected scene '%s' does not exist, select a valid one? \n You can change it later in \" Project Settings \" under the 'application' category. " ) , main_scene ) ) ;
pick_main_scene - > popup_centered_minsize ( ) ;
return false ;
}
if ( ResourceLoader : : get_resource_type ( main_scene ) ! = " PackedScene " ) {
current_option = - 1 ;
pick_main_scene - > set_text ( vformat ( TTR ( " Selected scene '%s' is not a scene file, select a valid one? \n You can change it later in \" Project Settings \" under the 'application' category. " ) , main_scene ) ) ;
pick_main_scene - > popup_centered_minsize ( ) ;
return false ;
}
return true ;
}
2019-07-18 04:08:24 +02:00
void EditorNode : : run_play ( ) {
_menu_option_confirm ( RUN_STOP , true ) ;
_run ( false ) ;
}
2020-04-05 16:19:24 +02:00
void EditorNode : : run_play_current ( ) {
_save_default_environment ( ) ;
_menu_option_confirm ( RUN_STOP , true ) ;
_run ( true ) ;
}
void EditorNode : : run_play_custom ( const String & p_custom ) {
_menu_option_confirm ( RUN_STOP , true ) ;
_run ( false , p_custom ) ;
}
2019-07-18 04:08:24 +02:00
void EditorNode : : run_stop ( ) {
_menu_option_confirm ( RUN_STOP , false ) ;
}
2020-04-05 16:19:24 +02:00
bool EditorNode : : is_run_playing ( ) const {
EditorRun : : Status status = editor_run . get_status ( ) ;
return ( status = = EditorRun : : STATUS_PLAY | | status = = EditorRun : : STATUS_PAUSED ) ;
}
String EditorNode : : get_run_playing_scene ( ) const {
String run_filename = editor_run . get_running_scene ( ) ;
if ( run_filename = = " " & & is_run_playing ( ) ) {
run_filename = GLOBAL_DEF ( " application/run/main_scene " , " " ) ; // Must be the main scene then.
}
return run_filename ;
}
2019-06-04 05:36:23 +02:00
int EditorNode : : get_current_tab ( ) {
return scene_tabs - > get_current_tab ( ) ;
}
void EditorNode : : set_current_tab ( int p_tab ) {
scene_tabs - > set_current_tab ( p_tab ) ;
}
2015-11-22 19:11:17 +01:00
void EditorNode : : _update_layouts_menu ( ) {
editor_layouts - > clear ( ) ;
2017-03-05 16:44:50 +01:00
overridden_default_layout = - 1 ;
2016-01-11 22:23:45 +01:00
2015-11-22 19:11:17 +01:00
editor_layouts - > set_size ( Vector2 ( ) ) ;
2017-03-05 16:44:50 +01:00
editor_layouts - > add_shortcut ( ED_SHORTCUT ( " layout/save " , TTR ( " Save Layout " ) ) , SETTINGS_LAYOUT_SAVE ) ;
editor_layouts - > add_shortcut ( ED_SHORTCUT ( " layout/delete " , TTR ( " Delete Layout " ) ) , SETTINGS_LAYOUT_DELETE ) ;
2015-11-22 19:11:17 +01:00
editor_layouts - > add_separator ( ) ;
2017-03-05 16:44:50 +01:00
editor_layouts - > add_shortcut ( ED_SHORTCUT ( " layout/default " , TTR ( " Default " ) ) , SETTINGS_LAYOUT_DEFAULT ) ;
2015-11-22 19:11:17 +01:00
Ref < ConfigFile > config ;
config . instance ( ) ;
2017-11-17 21:48:24 +01:00
Error err = config - > load ( EditorSettings : : get_singleton ( ) - > get_editor_layouts_config ( ) ) ;
2017-03-05 16:44:50 +01:00
if ( err ! = OK ) {
2015-11-22 19:11:17 +01:00
return ; //no config
}
List < String > layouts ;
config . ptr ( ) - > get_sections ( & layouts ) ;
2017-03-05 16:44:50 +01:00
for ( List < String > : : Element * E = layouts . front ( ) ; E ; E = E - > next ( ) ) {
String layout = E - > get ( ) ;
2015-11-22 19:11:17 +01:00
2017-03-05 16:44:50 +01:00
if ( layout = = TTR ( " Default " ) ) {
2016-01-11 22:23:45 +01:00
editor_layouts - > remove_item ( editor_layouts - > get_item_index ( SETTINGS_LAYOUT_DEFAULT ) ) ;
2017-03-05 16:44:50 +01:00
overridden_default_layout = editor_layouts - > get_item_count ( ) ;
2016-01-11 22:23:45 +01:00
}
editor_layouts - > add_item ( layout ) ;
2015-11-22 19:11:17 +01:00
}
}
void EditorNode : : _layout_menu_option ( int p_id ) {
switch ( p_id ) {
case SETTINGS_LAYOUT_SAVE : {
2017-03-05 16:44:50 +01:00
current_option = p_id ;
2016-05-04 03:25:37 +02:00
layout_dialog - > set_title ( TTR ( " Save Layout " ) ) ;
layout_dialog - > get_ok ( ) - > set_text ( TTR ( " Save " ) ) ;
2015-11-22 19:11:17 +01:00
layout_dialog - > popup_centered ( ) ;
2019-05-30 20:16:40 +02:00
layout_dialog - > set_name_line_enabled ( true ) ;
2015-11-22 19:11:17 +01:00
} break ;
case SETTINGS_LAYOUT_DELETE : {
2017-03-05 16:44:50 +01:00
current_option = p_id ;
2016-05-04 03:25:37 +02:00
layout_dialog - > set_title ( TTR ( " Delete Layout " ) ) ;
layout_dialog - > get_ok ( ) - > set_text ( TTR ( " Delete " ) ) ;
2015-11-22 19:11:17 +01:00
layout_dialog - > popup_centered ( ) ;
2019-05-30 20:16:40 +02:00
layout_dialog - > set_name_line_enabled ( false ) ;
2015-11-22 19:11:17 +01:00
} break ;
case SETTINGS_LAYOUT_DEFAULT : {
2016-01-11 22:23:45 +01:00
_load_docks_from_config ( default_layout , " docks " ) ;
2015-11-22 19:11:17 +01:00
_save_docks ( ) ;
} break ;
default : {
Ref < ConfigFile > config ;
config . instance ( ) ;
2017-11-17 21:48:24 +01:00
Error err = config - > load ( EditorSettings : : get_singleton ( ) - > get_editor_layouts_config ( ) ) ;
2017-03-05 16:44:50 +01:00
if ( err ! = OK ) {
2015-11-22 19:11:17 +01:00
return ; //no config
}
2015-12-14 16:44:15 +01:00
_load_docks_from_config ( config , editor_layouts - > get_item_text ( p_id ) ) ;
2015-11-22 19:11:17 +01:00
_save_docks ( ) ;
}
}
2015-06-22 05:03:19 +02:00
}
2015-07-26 15:44:10 +02:00
void EditorNode : : _scene_tab_script_edited ( int p_tab ) {
2017-03-05 16:44:50 +01:00
Ref < Script > script = editor_data . get_scene_root_script ( p_tab ) ;
2021-05-05 12:44:11 +02:00
if ( script . is_valid ( ) ) {
2018-05-17 08:01:47 +02:00
inspector_dock - > edit_resource ( script ) ;
2021-05-05 12:44:11 +02:00
}
2015-07-26 15:44:10 +02:00
}
2019-04-21 11:44:21 +02:00
void EditorNode : : _scene_tab_closed ( int p_tab , int option ) {
current_option = option ;
2015-11-19 14:15:17 +01:00
tab_closing = p_tab ;
2017-06-26 16:04:53 +02:00
Node * scene = editor_data . get_edited_scene_root ( p_tab ) ;
2017-07-09 20:48:39 +02:00
if ( ! scene ) {
_discard_changes ( ) ;
return ;
}
2016-05-02 13:40:44 +02:00
2021-10-28 14:35:34 +02:00
bool unsaved = ( p_tab = = editor_data . get_edited_scene ( ) )
? saved_version ! = editor_data . get_undo_redo ( ) . get_version ( )
: editor_data . get_scene_version ( p_tab ) ! = 0 ;
2016-05-02 13:40:44 +02:00
if ( unsaved ) {
2017-06-24 12:57:30 +02:00
save_confirmation - > get_ok ( ) - > set_text ( TTR ( " Save & Close " ) ) ;
2017-06-26 16:04:53 +02:00
save_confirmation - > set_text ( vformat ( TTR ( " Save changes to '%s' before closing? " ) , scene - > get_filename ( ) ! = " " ? scene - > get_filename ( ) : " unsaved scene " ) ) ;
2017-06-21 06:15:39 +02:00
save_confirmation - > popup_centered_minsize ( ) ;
2017-03-05 16:44:50 +01:00
} else {
2017-06-21 06:15:39 +02:00
_discard_changes ( ) ;
2015-11-19 14:15:17 +01:00
}
2017-11-25 00:32:54 +01:00
save_layout ( ) ;
2017-11-16 23:57:57 +01:00
_update_scene_tabs ( ) ;
2015-08-18 20:27:01 +02:00
}
2017-06-15 17:30:03 +02:00
void EditorNode : : _scene_tab_hover ( int p_tab ) {
2018-10-06 22:20:41 +02:00
if ( ! bool ( EDITOR_GET ( " interface/scene_tabs/show_thumbnail_on_hover " ) ) ) {
2017-06-15 17:30:03 +02:00
return ;
}
int current_tab = scene_tabs - > get_current_tab ( ) ;
if ( p_tab = = current_tab | | p_tab < 0 ) {
tab_preview_panel - > hide ( ) ;
} else {
String path = editor_data . get_scene_path ( p_tab ) ;
2018-10-21 16:38:01 +02:00
if ( path ! = String ( ) ) {
EditorResourcePreview : : get_singleton ( ) - > queue_resource_preview ( path , this , " _thumbnail_done " , p_tab ) ;
}
2017-06-15 17:30:03 +02:00
}
}
void EditorNode : : _scene_tab_exit ( ) {
tab_preview_panel - > hide ( ) ;
}
void EditorNode : : _scene_tab_input ( const Ref < InputEvent > & p_input ) {
Ref < InputEventMouseButton > mb = p_input ;
if ( mb . is_valid ( ) ) {
2017-07-01 18:23:16 +02:00
if ( scene_tabs - > get_hovered_tab ( ) > = 0 ) {
if ( mb - > get_button_index ( ) = = BUTTON_MIDDLE & & mb - > is_pressed ( ) ) {
_scene_tab_closed ( scene_tabs - > get_hovered_tab ( ) ) ;
}
} else {
if ( ( mb - > get_button_index ( ) = = BUTTON_LEFT & & mb - > is_doubleclick ( ) ) | | ( mb - > get_button_index ( ) = = BUTTON_MIDDLE & & mb - > is_pressed ( ) ) ) {
_menu_option_confirm ( FILE_NEW_SCENE , true ) ;
}
2017-06-15 17:30:03 +02:00
}
2018-01-02 08:10:49 +01:00
if ( mb - > get_button_index ( ) = = BUTTON_RIGHT & & mb - > is_pressed ( ) ) {
// context menu
scene_tabs_context_menu - > clear ( ) ;
scene_tabs_context_menu - > set_size ( Size2 ( 1 , 1 ) ) ;
scene_tabs_context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " editor/new_scene " ) , FILE_NEW_SCENE ) ;
if ( scene_tabs - > get_hovered_tab ( ) > = 0 ) {
scene_tabs_context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " editor/save_scene " ) , FILE_SAVE_SCENE ) ;
scene_tabs_context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " editor/save_scene_as " ) , FILE_SAVE_AS_SCENE ) ;
}
scene_tabs_context_menu - > add_shortcut ( ED_GET_SHORTCUT ( " editor/save_all_scenes " ) , FILE_SAVE_ALL_SCENES ) ;
if ( scene_tabs - > get_hovered_tab ( ) > = 0 ) {
scene_tabs_context_menu - > add_separator ( ) ;
2018-10-26 21:11:36 +02:00
scene_tabs_context_menu - > add_item ( TTR ( " Show in FileSystem " ) , FILE_SHOW_IN_FILESYSTEM ) ;
2018-01-02 08:10:49 +01:00
scene_tabs_context_menu - > add_item ( TTR ( " Play This Scene " ) , RUN_PLAY_SCENE ) ;
2019-04-10 17:21:26 +02:00
2019-04-21 11:44:21 +02:00
scene_tabs_context_menu - > add_separator ( ) ;
2019-04-10 17:21:26 +02:00
Ref < ShortCut > close_tab_sc = ED_GET_SHORTCUT ( " editor/close_scene " ) ;
close_tab_sc - > set_name ( TTR ( " Close Tab " ) ) ;
scene_tabs_context_menu - > add_shortcut ( close_tab_sc , FILE_CLOSE ) ;
Ref < ShortCut > undo_close_tab_sc = ED_GET_SHORTCUT ( " editor/reopen_closed_scene " ) ;
undo_close_tab_sc - > set_name ( TTR ( " Undo Close Tab " ) ) ;
scene_tabs_context_menu - > add_shortcut ( undo_close_tab_sc , FILE_OPEN_PREV ) ;
if ( previous_scenes . empty ( ) ) {
scene_tabs_context_menu - > set_item_disabled ( scene_tabs_context_menu - > get_item_index ( FILE_OPEN_PREV ) , true ) ;
}
2019-04-21 11:44:21 +02:00
scene_tabs_context_menu - > add_item ( TTR ( " Close Other Tabs " ) , FILE_CLOSE_OTHERS ) ;
scene_tabs_context_menu - > add_item ( TTR ( " Close Tabs to the Right " ) , FILE_CLOSE_RIGHT ) ;
scene_tabs_context_menu - > add_item ( TTR ( " Close All Tabs " ) , FILE_CLOSE_ALL ) ;
2018-01-02 08:10:49 +01:00
}
scene_tabs_context_menu - > set_position ( mb - > get_global_position ( ) ) ;
scene_tabs_context_menu - > popup ( ) ;
}
2021-04-07 15:25:44 +02:00
if ( mb - > get_button_index ( ) = = BUTTON_WHEEL_UP & & mb - > is_pressed ( ) ) {
int previous_tab = editor_data . get_edited_scene ( ) - 1 ;
previous_tab = previous_tab > = 0 ? previous_tab : editor_data . get_edited_scene_count ( ) - 1 ;
_scene_tab_changed ( previous_tab ) ;
}
if ( mb - > get_button_index ( ) = = BUTTON_WHEEL_DOWN & & mb - > is_pressed ( ) ) {
int next_tab = editor_data . get_edited_scene ( ) + 1 ;
next_tab % = editor_data . get_edited_scene_count ( ) ;
_scene_tab_changed ( next_tab ) ;
}
2017-06-15 17:30:03 +02:00
}
}
2017-07-05 15:44:53 +02:00
void EditorNode : : _reposition_active_tab ( int idx_to ) {
editor_data . move_edited_scene_to_index ( idx_to ) ;
_update_scene_tabs ( ) ;
}
2018-09-12 13:10:49 +02:00
void EditorNode : : _thumbnail_done ( const String & p_path , const Ref < Texture > & p_preview , const Ref < Texture > & p_small_preview , const Variant & p_udata ) {
2017-06-15 17:30:03 +02:00
int p_tab = p_udata . operator signed int ( ) ;
if ( p_preview . is_valid ( ) ) {
Rect2 rect = scene_tabs - > get_tab_rect ( p_tab ) ;
rect . position + = scene_tabs - > get_global_position ( ) ;
tab_preview - > set_texture ( p_preview ) ;
tab_preview_panel - > set_position ( rect . position + Vector2 ( 0 , rect . size . height ) ) ;
tab_preview_panel - > show ( ) ;
}
}
2015-06-22 05:03:19 +02:00
void EditorNode : : _scene_tab_changed ( int p_tab ) {
2017-06-15 17:30:03 +02:00
tab_preview_panel - > hide ( ) ;
2015-06-22 05:03:19 +02:00
2017-03-05 16:44:50 +01:00
bool unsaved = ( saved_version ! = editor_data . get_undo_redo ( ) . get_version ( ) ) ;
2015-06-22 05:03:19 +02:00
2021-05-05 12:44:11 +02:00
if ( p_tab = = editor_data . get_edited_scene ( ) ) {
2015-06-22 05:03:19 +02:00
return ; //pointless
2021-05-05 12:44:11 +02:00
}
2015-06-22 05:03:19 +02:00
uint64_t next_scene_version = editor_data . get_scene_version ( p_tab ) ;
2016-05-04 03:25:37 +02:00
editor_data . get_undo_redo ( ) . create_action ( TTR ( " Switch Scene Tab " ) ) ;
2017-03-05 16:44:50 +01:00
editor_data . get_undo_redo ( ) . add_do_method ( this , " set_current_version " , unsaved ? saved_version : 0 ) ;
editor_data . get_undo_redo ( ) . add_do_method ( this , " set_current_scene " , p_tab ) ;
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 ) ;
2015-06-22 05:03:19 +02:00
2017-03-05 16:44:50 +01:00
editor_data . get_undo_redo ( ) . add_undo_method ( this , " set_current_version " , next_scene_version ) ;
editor_data . get_undo_redo ( ) . add_undo_method ( this , " set_current_scene " , editor_data . get_edited_scene ( ) ) ;
editor_data . get_undo_redo ( ) . add_undo_method ( this , " set_current_version " , saved_version ) ;
2015-06-22 05:03:19 +02:00
editor_data . get_undo_redo ( ) . commit_action ( ) ;
2015-06-14 03:12:53 +02:00
}
2014-06-19 07:23:03 +02:00
2017-03-05 16:44:50 +01:00
ToolButton * EditorNode : : add_bottom_panel_item ( String p_text , Control * p_item ) {
ToolButton * tb = memnew ( ToolButton ) ;
tb - > connect ( " toggled " , this , " _bottom_panel_switch " , varray ( bottom_panel_items . size ( ) ) ) ;
2016-01-18 00:03:57 +01:00
tb - > set_text ( p_text ) ;
tb - > set_toggle_mode ( true ) ;
tb - > set_focus_mode ( Control : : FOCUS_NONE ) ;
bottom_panel_vb - > add_child ( p_item ) ;
bottom_panel_hb - > raise ( ) ;
2018-07-16 03:38:14 +02:00
bottom_panel_hb_editors - > add_child ( tb ) ;
2016-01-18 00:03:57 +01:00
p_item - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
p_item - > hide ( ) ;
BottomPanelItem bpi ;
2017-03-05 16:44:50 +01:00
bpi . button = tb ;
bpi . control = p_item ;
bpi . name = p_text ;
2016-01-18 00:03:57 +01:00
bottom_panel_items . push_back ( bpi ) ;
return tb ;
}
2016-01-24 16:26:03 +01:00
bool EditorNode : : are_bottom_panels_hidden ( ) const {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < bottom_panel_items . size ( ) ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( bottom_panel_items [ i ] . button - > is_pressed ( ) ) {
2016-01-24 16:26:03 +01:00
return false ;
2021-05-05 12:44:11 +02:00
}
2016-01-24 16:26:03 +01:00
}
return true ;
}
2016-01-18 00:03:57 +01:00
void EditorNode : : hide_bottom_panel ( ) {
2019-03-16 07:39:49 +01:00
for ( int i = 0 ; i < bottom_panel_items . size ( ) ; i + + ) {
if ( bottom_panel_items [ i ] . control - > is_visible ( ) ) {
_bottom_panel_switch ( false , i ) ;
break ;
}
}
2016-01-18 00:03:57 +01:00
}
void EditorNode : : make_bottom_panel_item_visible ( Control * p_item ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < bottom_panel_items . size ( ) ; i + + ) {
if ( bottom_panel_items [ i ] . control = = p_item ) {
_bottom_panel_switch ( true , i ) ;
2016-01-18 00:03:57 +01:00
break ;
}
}
}
void EditorNode : : raise_bottom_panel_item ( Control * p_item ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < bottom_panel_items . size ( ) ; i + + ) {
if ( bottom_panel_items [ i ] . control = = p_item ) {
2016-01-18 00:03:57 +01:00
bottom_panel_items [ i ] . button - > raise ( ) ;
2018-07-25 03:11:03 +02:00
SWAP ( bottom_panel_items . write [ i ] , bottom_panel_items . write [ bottom_panel_items . size ( ) - 1 ] ) ;
2016-01-18 00:03:57 +01:00
break ;
}
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < bottom_panel_items . size ( ) ; i + + ) {
bottom_panel_items [ i ] . button - > disconnect ( " toggled " , this , " _bottom_panel_switch " ) ;
bottom_panel_items [ i ] . button - > connect ( " toggled " , this , " _bottom_panel_switch " , varray ( i ) ) ;
2016-01-18 00:03:57 +01:00
}
}
2016-02-28 20:58:17 +01:00
void EditorNode : : remove_bottom_panel_item ( Control * p_item ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < bottom_panel_items . size ( ) ; i + + ) {
if ( bottom_panel_items [ i ] . control = = p_item ) {
2017-01-13 14:45:50 +01:00
if ( p_item - > is_visible_in_tree ( ) ) {
2019-03-16 07:39:49 +01:00
_bottom_panel_switch ( false , i ) ;
2016-02-28 20:58:17 +01:00
}
bottom_panel_vb - > remove_child ( bottom_panel_items [ i ] . control ) ;
2018-07-16 03:38:14 +02:00
bottom_panel_hb_editors - > remove_child ( bottom_panel_items [ i ] . button ) ;
2017-03-05 16:44:50 +01:00
memdelete ( bottom_panel_items [ i ] . button ) ;
2016-02-28 20:58:17 +01:00
bottom_panel_items . remove ( i ) ;
break ;
}
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < bottom_panel_items . size ( ) ; i + + ) {
bottom_panel_items [ i ] . button - > disconnect ( " toggled " , this , " _bottom_panel_switch " ) ;
bottom_panel_items [ i ] . button - > connect ( " toggled " , this , " _bottom_panel_switch " , varray ( i ) ) ;
2016-02-28 20:58:17 +01:00
}
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _bottom_panel_switch ( bool p_enable , int p_idx ) {
ERR_FAIL_INDEX ( p_idx , bottom_panel_items . size ( ) ) ;
2016-01-18 00:03:57 +01:00
2019-03-16 07:39:49 +01:00
if ( bottom_panel_items [ p_idx ] . control - > is_visible ( ) = = p_enable ) {
return ;
}
2016-01-18 00:03:57 +01:00
if ( p_enable ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < bottom_panel_items . size ( ) ; i + + ) {
bottom_panel_items [ i ] . button - > set_pressed ( i = = p_idx ) ;
bottom_panel_items [ i ] . control - > set_visible ( i = = p_idx ) ;
2016-01-18 00:03:57 +01:00
}
2018-01-18 21:37:17 +01:00
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
2017-09-18 21:06:55 +02:00
bottom_panel - > add_style_override ( " panel " , gui_base - > get_stylebox ( " BottomPanelDebuggerOverride " , " EditorStyles " ) ) ;
} else {
bottom_panel - > add_style_override ( " panel " , gui_base - > get_stylebox ( " panel " , " TabContainer " ) ) ;
}
2016-01-18 00:03:57 +01:00
center_split - > set_dragger_visibility ( SplitContainer : : DRAGGER_VISIBLE ) ;
center_split - > set_collapsed ( false ) ;
2018-07-16 03:38:14 +02:00
if ( bottom_panel_raise - > is_pressed ( ) ) {
top_split - > hide ( ) ;
}
bottom_panel_raise - > show ( ) ;
2016-01-18 00:03:57 +01:00
} else {
2017-09-18 01:58:36 +02:00
bottom_panel - > add_style_override ( " panel " , gui_base - > get_stylebox ( " panel " , " TabContainer " ) ) ;
2019-03-16 07:39:49 +01:00
bottom_panel_items [ p_idx ] . button - > set_pressed ( false ) ;
bottom_panel_items [ p_idx ] . control - > set_visible ( false ) ;
2016-01-18 00:03:57 +01:00
center_split - > set_dragger_visibility ( SplitContainer : : DRAGGER_HIDDEN ) ;
center_split - > set_collapsed ( true ) ;
2018-07-16 03:38:14 +02:00
bottom_panel_raise - > hide ( ) ;
if ( bottom_panel_raise - > is_pressed ( ) ) {
top_split - > show ( ) ;
}
2016-01-18 00:03:57 +01:00
}
}
2016-05-30 20:29:43 +02:00
void EditorNode : : set_docks_visible ( bool p_show ) {
docks_visible = p_show ;
2022-11-03 13:02:11 +01:00
_update_dock_slots_visibility ( true ) ;
2016-05-30 20:29:43 +02:00
}
bool EditorNode : : get_docks_visible ( ) const {
return docks_visible ;
}
2016-09-13 14:46:17 +02:00
void EditorNode : : _toggle_distraction_free_mode ( ) {
2017-09-29 18:52:56 +02:00
if ( EditorSettings : : get_singleton ( ) - > get ( " interface/editor/separate_distraction_mode " ) ) {
2017-04-25 13:48:35 +02:00
int screen = - 1 ;
for ( int i = 0 ; i < editor_table . size ( ) ; i + + ) {
if ( editor_plugin_screen = = editor_table [ i ] ) {
screen = i ;
break ;
}
}
if ( screen = = EDITOR_SCRIPT ) {
2017-05-06 10:31:36 +02:00
script_distraction = ! script_distraction ;
2017-04-25 13:48:35 +02:00
set_distraction_free_mode ( script_distraction ) ;
} else {
2017-05-06 10:31:36 +02:00
scene_distraction = ! scene_distraction ;
2017-04-25 13:48:35 +02:00
set_distraction_free_mode ( scene_distraction ) ;
}
} else {
set_distraction_free_mode ( distraction_free - > is_pressed ( ) ) ;
}
2016-09-13 14:46:17 +02:00
}
2016-05-30 20:29:43 +02:00
void EditorNode : : set_distraction_free_mode ( bool p_enter ) {
2016-09-13 14:46:17 +02:00
distraction_free - > set_pressed ( p_enter ) ;
2016-05-30 20:29:43 +02:00
if ( p_enter ) {
if ( docks_visible ) {
set_docks_visible ( false ) ;
}
} else {
set_docks_visible ( true ) ;
}
}
2020-05-31 19:58:15 +02:00
bool EditorNode : : is_distraction_free_mode_enabled ( ) const {
2016-09-13 14:46:17 +02:00
return distraction_free - > is_pressed ( ) ;
2016-05-30 20:29:43 +02:00
}
2016-02-28 03:10:44 +01:00
2017-03-05 16:44:50 +01:00
void EditorNode : : add_control_to_dock ( DockSlot p_slot , Control * p_control ) {
ERR_FAIL_INDEX ( p_slot , DOCK_SLOT_MAX ) ;
2016-02-28 03:10:44 +01:00
dock_slot [ p_slot ] - > add_child ( p_control ) ;
_update_dock_slots_visibility ( ) ;
}
2017-03-05 16:44:50 +01:00
void EditorNode : : remove_control_from_dock ( Control * p_control ) {
2021-05-04 16:00:45 +02:00
Control * dock = nullptr ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < DOCK_SLOT_MAX ; i + + ) {
if ( p_control - > get_parent ( ) = = dock_slot [ i ] ) {
dock = dock_slot [ i ] ;
2016-02-28 03:10:44 +01:00
break ;
}
}
2019-08-15 04:57:49 +02:00
ERR_FAIL_COND_MSG ( ! dock , " Control was not in dock. " ) ;
2016-02-28 03:10:44 +01:00
dock - > remove_child ( p_control ) ;
_update_dock_slots_visibility ( ) ;
}
2017-03-05 16:44:50 +01:00
Variant EditorNode : : drag_resource ( const Ref < Resource > & p_res , Control * p_from ) {
Control * drag_control = memnew ( Control ) ;
TextureRect * drag_preview = memnew ( TextureRect ) ;
Label * label = memnew ( Label ) ;
2016-05-11 16:46:08 +02:00
Ref < Texture > preview ;
{
//todo make proper previews
2017-09-12 21:32:04 +02:00
Ref < ImageTexture > pic = gui_base - > get_icon ( " FileBigThumb " , " EditorIcons " ) ;
2017-05-17 12:36:47 +02:00
Ref < Image > img = pic - > get_data ( ) ;
img = img - > duplicate ( ) ;
img - > resize ( 48 , 48 ) ; //meh
2017-03-05 16:44:50 +01:00
Ref < ImageTexture > resized_pic = Ref < ImageTexture > ( memnew ( ImageTexture ) ) ;
2016-05-11 16:46:08 +02:00
resized_pic - > create_from_image ( img ) ;
2017-03-05 16:44:50 +01:00
preview = resized_pic ;
2016-05-11 16:46:08 +02:00
}
drag_preview - > set_texture ( preview ) ;
drag_control - > add_child ( drag_preview ) ;
if ( p_res - > get_path ( ) . is_resource_file ( ) ) {
label - > set_text ( p_res - > get_path ( ) . get_file ( ) ) ;
2017-03-05 16:44:50 +01:00
} else if ( p_res - > get_name ( ) ! = " " ) {
2016-05-11 16:46:08 +02:00
label - > set_text ( p_res - > get_name ( ) ) ;
} else {
2017-01-03 03:03:46 +01:00
label - > set_text ( p_res - > get_class ( ) ) ;
2016-05-11 16:46:08 +02:00
}
drag_control - > add_child ( label ) ;
p_from - > set_drag_preview ( drag_control ) ; //wait until it enters scene
2017-03-29 17:29:38 +02:00
label - > set_position ( Point2 ( ( preview - > get_width ( ) - label - > get_minimum_size ( ) . width ) / 2 , preview - > get_height ( ) ) ) ;
2016-05-11 16:46:08 +02:00
Dictionary drag_data ;
2017-03-05 16:44:50 +01:00
drag_data [ " type " ] = " resource " ;
drag_data [ " resource " ] = p_res ;
drag_data [ " from " ] = p_from ;
2016-05-11 16:46:08 +02:00
return drag_data ;
}
2017-10-25 00:09:04 +02:00
Variant EditorNode : : drag_files_and_dirs ( const Vector < String > & p_paths , Control * p_from ) {
bool has_folder = false ;
bool has_file = false ;
for ( int i = 0 ; i < p_paths . size ( ) ; i + + ) {
bool is_folder = p_paths [ i ] . ends_with ( " / " ) ;
has_folder | = is_folder ;
has_file | = ! is_folder ;
}
int max_rows = 6 ;
2019-09-30 18:36:49 +02:00
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.
2017-10-25 00:09:04 +02:00
VBoxContainer * vbox = memnew ( VBoxContainer ) ;
for ( int i = 0 ; i < num_rows ; i + + ) {
HBoxContainer * hbox = memnew ( HBoxContainer ) ;
TextureRect * icon = memnew ( TextureRect ) ;
2017-03-05 16:44:50 +01:00
Label * label = memnew ( Label ) ;
2016-05-11 16:46:08 +02:00
2017-10-25 00:09:04 +02:00
if ( p_paths [ i ] . ends_with ( " / " ) ) {
label - > set_text ( p_paths [ i ] . substr ( 0 , p_paths [ i ] . length ( ) - 1 ) . get_file ( ) ) ;
icon - > set_texture ( gui_base - > get_icon ( " Folder " , " EditorIcons " ) ) ;
} else {
label - > set_text ( p_paths [ i ] . get_file ( ) ) ;
icon - > set_texture ( gui_base - > get_icon ( " File " , " EditorIcons " ) ) ;
}
2019-09-30 18:36:49 +02:00
icon - > set_stretch_mode ( TextureRect : : STRETCH_KEEP_CENTERED ) ;
2017-10-25 00:09:04 +02:00
icon - > set_size ( Size2 ( 16 , 16 ) ) ;
hbox - > add_child ( icon ) ;
hbox - > add_child ( label ) ;
vbox - > add_child ( hbox ) ;
2016-05-11 16:46:08 +02:00
}
2017-10-25 00:09:04 +02:00
if ( p_paths . size ( ) > num_rows ) {
2017-03-05 16:44:50 +01:00
Label * label = memnew ( Label ) ;
2017-10-25 00:09:04 +02:00
if ( has_file & & has_folder ) {
label - > set_text ( vformat ( TTR ( " %d more files or folders " ) , p_paths . size ( ) - num_rows ) ) ;
} else if ( has_folder ) {
label - > set_text ( vformat ( TTR ( " %d more folders " ) , p_paths . size ( ) - num_rows ) ) ;
} else {
label - > set_text ( vformat ( TTR ( " %d more files " ) , p_paths . size ( ) - num_rows ) ) ;
}
vbox - > add_child ( label ) ;
2016-05-11 16:46:08 +02:00
}
2017-10-25 00:09:04 +02:00
p_from - > set_drag_preview ( vbox ) ; //wait until it enters scene
2016-05-11 16:46:08 +02:00
Dictionary drag_data ;
2017-10-25 00:09:04 +02:00
drag_data [ " type " ] = has_folder ? " files_and_dirs " : " files " ;
drag_data [ " files " ] = p_paths ;
2017-03-05 16:44:50 +01:00
drag_data [ " from " ] = p_from ;
2016-05-11 16:46:08 +02:00
return drag_data ;
}
2018-03-17 02:50:35 +01:00
void EditorNode : : add_tool_menu_item ( const String & p_name , Object * p_handler , const String & p_callback , const Variant & p_ud ) {
ERR_FAIL_NULL ( p_handler ) ;
int idx = tool_menu - > get_item_count ( ) ;
tool_menu - > add_item ( p_name , TOOLS_CUSTOM ) ;
Array parameters ;
parameters . push_back ( p_handler - > get_instance_id ( ) ) ;
parameters . push_back ( p_callback ) ;
parameters . push_back ( p_ud ) ;
tool_menu - > set_item_metadata ( idx , parameters ) ;
}
void EditorNode : : add_tool_submenu_item ( const String & p_name , PopupMenu * p_submenu ) {
ERR_FAIL_NULL ( p_submenu ) ;
2021-05-04 16:00:45 +02:00
ERR_FAIL_COND ( p_submenu - > get_parent ( ) ! = nullptr ) ;
2018-03-17 02:50:35 +01:00
tool_menu - > add_child ( p_submenu ) ;
tool_menu - > add_submenu_item ( p_name , p_submenu - > get_name ( ) , TOOLS_CUSTOM ) ;
}
void EditorNode : : remove_tool_menu_item ( const String & p_name ) {
for ( int i = 0 ; i < tool_menu - > get_item_count ( ) ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( tool_menu - > get_item_id ( i ) ! = TOOLS_CUSTOM ) {
2018-03-17 02:50:35 +01:00
continue ;
2021-05-05 12:44:11 +02:00
}
2018-03-17 02:50:35 +01:00
if ( tool_menu - > get_item_text ( i ) = = p_name ) {
if ( tool_menu - > get_item_submenu ( i ) ! = " " ) {
Node * n = tool_menu - > get_node ( tool_menu - > get_item_submenu ( i ) ) ;
tool_menu - > remove_child ( n ) ;
memdelete ( n ) ;
}
tool_menu - > remove_item ( i ) ;
tool_menu - > set_as_minsize ( ) ;
return ;
}
}
}
2019-02-06 14:57:06 +01:00
void EditorNode : : _global_menu_action ( const Variant & p_id , const Variant & p_meta ) {
int id = ( int ) p_id ;
if ( id = = GLOBAL_NEW_WINDOW ) {
if ( OS : : get_singleton ( ) - > get_main_loop ( ) ) {
List < String > args ;
2021-03-14 16:56:02 +01:00
args . push_back ( " -p " ) ;
2019-02-06 14:57:06 +01:00
String exec = OS : : get_singleton ( ) - > get_executable_path ( ) ;
OS : : ProcessID pid = 0 ;
OS : : get_singleton ( ) - > execute ( exec , args , false , & pid ) ;
}
} else if ( id = = GLOBAL_SCENE ) {
int idx = ( int ) p_meta ;
scene_tabs - > set_current_tab ( idx ) ;
}
}
2017-03-05 16:44:50 +01:00
void EditorNode : : _dropped_files ( const Vector < String > & p_files , int p_screen ) {
2019-02-19 17:21:05 +01:00
String to_path = ProjectSettings : : get_singleton ( ) - > globalize_path ( get_filesystem_dock ( ) - > get_selected_path ( ) ) ;
2017-11-17 21:52:03 +01:00
2019-03-25 22:39:45 +01:00
_add_dropped_files_recursive ( p_files , to_path ) ;
EditorFileSystem : : get_singleton ( ) - > scan_changes ( ) ;
}
void EditorNode : : _add_dropped_files_recursive ( const Vector < String > & p_files , String to_path ) {
DirAccessRef dir = DirAccess : : create ( DirAccess : : ACCESS_FILESYSTEM ) ;
2017-11-17 21:52:03 +01:00
for ( int i = 0 ; i < p_files . size ( ) ; i + + ) {
String from = p_files [ i ] ;
2019-03-25 22:39:45 +01:00
String to = to_path . plus_file ( from . get_file ( ) ) ;
if ( dir - > dir_exists ( from ) ) {
Vector < String > sub_files ;
DirAccessRef sub_dir = DirAccess : : open ( from ) ;
sub_dir - > list_dir_begin ( ) ;
String next_file = sub_dir - > get_next ( ) ;
while ( next_file ! = " " ) {
if ( next_file = = " . " | | next_file = = " .. " ) {
next_file = sub_dir - > get_next ( ) ;
continue ;
}
sub_files . push_back ( from . plus_file ( next_file ) ) ;
next_file = sub_dir - > get_next ( ) ;
}
if ( ! sub_files . empty ( ) ) {
dir - > make_dir ( to ) ;
_add_dropped_files_recursive ( sub_files , to ) ;
}
continue ;
}
2017-11-17 21:52:03 +01:00
dir - > copy ( from , to ) ;
2017-08-26 17:46:49 +02:00
}
2016-05-27 19:18:40 +02:00
}
2017-08-26 17:46:49 +02:00
2017-03-05 16:44:50 +01:00
void EditorNode : : _file_access_close_error_notify ( const String & p_str ) {
2022-03-07 14:50:02 +01:00
add_io_error ( vformat ( TTR ( " Unable to write to file '%s', file in use, locked or lacking permissions. " ) , p_str ) ) ;
2016-06-13 15:10:50 +02:00
}
2016-05-27 19:18:40 +02:00
2017-03-05 16:44:50 +01:00
void EditorNode : : reload_scene ( const String & p_path ) {
2017-08-31 23:57:03 +02:00
//first of all, reload internal textures, materials, meshes, etc. as they might have changed on disk
2016-06-28 23:53:31 +02:00
2021-05-04 14:20:36 +02:00
List < Ref < Resource > > cached ;
2016-06-28 23:53:31 +02:00
ResourceCache : : get_cached_resources ( & cached ) ;
2021-05-04 14:20:36 +02:00
List < Ref < Resource > > to_clear ; //clear internal resources from previous scene from being used
for ( List < Ref < Resource > > : : Element * E = cached . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-31 23:57:03 +02:00
if ( E - > get ( ) - > get_path ( ) . begins_with ( p_path + " :: " ) ) { //subresources of existing scene
2016-06-28 23:53:31 +02:00
to_clear . push_back ( E - > get ( ) ) ;
}
}
//so reload reloads everything, clear subresources of previous scene
2017-03-05 16:44:50 +01:00
while ( to_clear . front ( ) ) {
2016-06-28 23:53:31 +02:00
to_clear . front ( ) - > get ( ) - > set_path ( " " ) ;
to_clear . pop_front ( ) ;
}
2017-03-05 16:44:50 +01:00
int scene_idx = - 1 ;
for ( int i = 0 ; i < editor_data . get_edited_scene_count ( ) ; i + + ) {
if ( editor_data . get_scene_path ( i ) = = p_path ) {
scene_idx = i ;
2016-06-28 23:53:31 +02:00
break ;
}
}
int current_tab = editor_data . get_edited_scene ( ) ;
2017-03-05 16:44:50 +01:00
if ( scene_idx = = - 1 ) {
2016-06-28 23:53:31 +02:00
if ( get_edited_scene ( ) ) {
2019-06-04 05:36:23 +02:00
//scene is not open, so at it might be instanced. We'll refresh the whole scene later.
2016-06-28 23:53:31 +02:00
editor_data . get_undo_redo ( ) . clear_history ( ) ;
}
return ;
}
2017-03-05 16:44:50 +01:00
if ( current_tab = = scene_idx ) {
2016-06-28 23:53:31 +02:00
editor_data . apply_changes_in_editors ( ) ;
_set_scene_metadata ( p_path ) ;
}
2019-06-04 05:36:23 +02:00
2016-06-28 23:53:31 +02:00
//remove scene
2019-06-04 05:36:23 +02:00
_remove_scene ( scene_idx , false ) ;
2017-08-31 23:57:03 +02:00
2019-06-04 05:36:23 +02:00
//reload scene
2017-08-31 23:57:03 +02:00
load_scene ( p_path , true , false , true , true ) ;
2019-06-04 05:36:23 +02:00
2016-06-28 23:53:31 +02:00
//adjust index so tab is back a the previous position
editor_data . move_edited_scene_to_index ( scene_idx ) ;
get_undo_redo ( ) - > clear_history ( ) ;
2019-06-04 05:36:23 +02:00
2016-06-28 23:53:31 +02:00
//recover the tab
scene_tabs - > set_current_tab ( current_tab ) ;
}
2017-03-05 16:44:50 +01:00
int EditorNode : : plugin_init_callback_count = 0 ;
2016-08-07 00:00:54 +02:00
void EditorNode : : add_plugin_init_callback ( EditorPluginInitializeCallback p_callback ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( plugin_init_callback_count = = MAX_INIT_CALLBACKS ) ;
2016-08-07 00:00:54 +02:00
2017-03-05 16:44:50 +01:00
plugin_init_callbacks [ plugin_init_callback_count + + ] = p_callback ;
2016-08-07 00:00:54 +02:00
}
EditorPluginInitializeCallback EditorNode : : plugin_init_callbacks [ EditorNode : : MAX_INIT_CALLBACKS ] ;
2017-03-05 16:44:50 +01:00
int EditorNode : : build_callback_count = 0 ;
2016-09-15 00:37:37 +02:00
void EditorNode : : add_build_callback ( EditorBuildCallback p_callback ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( build_callback_count = = MAX_INIT_CALLBACKS ) ;
2016-09-15 00:37:37 +02:00
2017-03-05 16:44:50 +01:00
build_callbacks [ build_callback_count + + ] = p_callback ;
2016-09-15 00:37:37 +02:00
}
2017-08-29 23:59:20 +02:00
EditorBuildCallback EditorNode : : build_callbacks [ EditorNode : : MAX_BUILD_CALLBACKS ] ;
2016-09-15 00:37:37 +02:00
2018-02-14 16:23:04 +01:00
bool EditorNode : : call_build ( ) {
2018-01-08 16:55:22 +01:00
bool builds_successful = true ;
for ( int i = 0 ; i < build_callback_count & & builds_successful ; i + + ) {
if ( ! build_callbacks [ i ] ( ) ) {
ERR_PRINT ( " A Godot Engine build callback failed. " ) ;
builds_successful = false ;
}
2016-09-15 00:44:08 +02:00
}
2017-08-29 23:59:20 +02:00
2018-01-08 16:55:22 +01:00
if ( builds_successful & & ! editor_data . call_build ( ) ) {
ERR_PRINT ( " An EditorPlugin build callback failed. " ) ;
builds_successful = false ;
}
return builds_successful ;
2016-09-15 00:44:08 +02:00
}
2016-09-15 00:37:37 +02:00
2017-03-05 16:44:50 +01:00
void EditorNode : : _inherit_imported ( const String & p_action ) {
2017-02-05 00:31:15 +01:00
open_imported - > hide ( ) ;
2017-03-05 16:44:50 +01:00
load_scene ( open_import_request , true , true ) ;
2017-02-05 00:31:15 +01:00
}
void EditorNode : : _open_imported ( ) {
2017-03-05 16:44:50 +01:00
load_scene ( open_import_request , true , false , true , true ) ;
2017-02-05 00:31:15 +01:00
}
2019-08-29 15:51:23 +02:00
void EditorNode : : dim_editor ( bool p_dimming , bool p_force_dim ) {
2019-10-31 20:58:53 +01:00
// Dimming can be forced regardless of the editor setting, which is useful when quitting the editor.
2019-08-29 15:51:23 +02:00
if ( ( p_force_dim | | EditorSettings : : get_singleton ( ) - > get ( " interface/editor/dim_editor_on_dialog_popup " ) ) & & p_dimming ) {
2019-10-31 20:58:53 +01:00
dimmed = true ;
2019-08-29 15:51:23 +02:00
gui_base - > set_modulate ( Color ( 0.5 , 0.5 , 0.5 ) ) ;
2017-03-06 20:11:56 +01:00
} else {
2019-10-31 20:58:53 +01:00
dimmed = false ;
2019-08-29 15:51:23 +02:00
gui_base - > set_modulate ( Color ( 1 , 1 , 1 ) ) ;
2017-03-06 20:11:56 +01:00
}
}
2019-10-31 20:58:53 +01:00
bool EditorNode : : is_editor_dimmed ( ) const {
return dimmed ;
}
2017-03-21 03:31:41 +01:00
void EditorNode : : open_export_template_manager ( ) {
export_template_manager - > popup_manager ( ) ;
}
2017-09-22 14:20:28 +02:00
void EditorNode : : add_resource_conversion_plugin ( const Ref < EditorResourceConversionPlugin > & p_plugin ) {
resource_conversion_plugins . push_back ( p_plugin ) ;
}
void EditorNode : : remove_resource_conversion_plugin ( const Ref < EditorResourceConversionPlugin > & p_plugin ) {
resource_conversion_plugins . erase ( p_plugin ) ;
}
2021-05-04 14:20:36 +02:00
Vector < Ref < EditorResourceConversionPlugin > > EditorNode : : find_resource_conversion_plugin ( const Ref < Resource > & p_for_resource ) {
Vector < Ref < EditorResourceConversionPlugin > > ret ;
2017-09-22 14:20:28 +02:00
for ( int i = 0 ; i < resource_conversion_plugins . size ( ) ; i + + ) {
if ( resource_conversion_plugins [ i ] . is_valid ( ) & & resource_conversion_plugins [ i ] - > handles ( p_for_resource ) ) {
ret . push_back ( resource_conversion_plugins [ i ] ) ;
}
}
return ret ;
}
2018-07-16 03:38:14 +02:00
void EditorNode : : _bottom_panel_raise_toggled ( bool p_pressed ) {
2019-07-29 23:08:05 +02:00
top_split - > set_visible ( ! p_pressed ) ;
2018-07-16 03:38:14 +02:00
}
2018-09-28 21:40:20 +02:00
void EditorNode : : _update_video_driver_color ( ) {
2019-07-29 23:08:05 +02:00
// TODO: Probably should de-hardcode this and add to editor settings.
2018-09-28 21:40:20 +02:00
if ( video_driver - > get_text ( ) = = " GLES2 " ) {
video_driver - > add_color_override ( " font_color " , Color : : hex ( 0x5586a4ff ) ) ;
} else if ( video_driver - > get_text ( ) = = " GLES3 " ) {
video_driver - > add_color_override ( " font_color " , Color : : hex ( 0xa5557dff ) ) ;
}
}
2018-07-19 23:58:15 +02:00
void EditorNode : : _video_driver_selected ( int p_which ) {
String driver = video_driver - > get_item_metadata ( p_which ) ;
String current = OS : : get_singleton ( ) - > get_video_driver_name ( OS : : get_singleton ( ) - > get_current_video_driver ( ) ) ;
if ( driver = = current ) {
return ;
}
video_driver_request = driver ;
video_restart_dialog - > popup_centered_minsize ( ) ;
video_driver - > select ( video_driver_current ) ;
2018-09-28 21:40:20 +02:00
_update_video_driver_color ( ) ;
2018-07-19 23:58:15 +02:00
}
2018-10-29 20:36:31 +01:00
void EditorNode : : _resource_saved ( RES p_resource , const String & p_path ) {
if ( EditorFileSystem : : get_singleton ( ) ) {
EditorFileSystem : : get_singleton ( ) - > update_file ( p_path ) ;
}
singleton - > editor_folding . save_resource_folding ( p_resource , p_path ) ;
}
void EditorNode : : _resource_loaded ( RES p_resource , const String & p_path ) {
singleton - > editor_folding . load_resource_folding ( p_resource , p_path ) ;
}
2022-03-28 04:49:13 +02:00
void EditorNode : : _project_settings_changed ( ) {
SceneTree * tree = get_tree ( ) ;
tree - > set_debug_collisions_color ( GLOBAL_GET ( " debug/shapes/collision/shape_color " ) ) ;
tree - > set_debug_collision_contact_color ( GLOBAL_GET ( " debug/shapes/collision/contact_color " ) ) ;
tree - > set_debug_navigation_color ( GLOBAL_GET ( " debug/shapes/navigation/geometry_color " ) ) ;
tree - > set_debug_navigation_disabled_color ( GLOBAL_GET ( " debug/shapes/navigation/disabled_geometry_color " ) ) ;
2022-12-01 05:54:10 +01:00
_update_title ( ) ;
2022-03-28 04:49:13 +02:00
}
2019-04-09 00:18:03 +02:00
void EditorNode : : _feature_profile_changed ( ) {
Ref < EditorFeatureProfile > profile = feature_profile_manager - > get_current_profile ( ) ;
TabContainer * import_tabs = cast_to < TabContainer > ( import_dock - > get_parent ( ) ) ;
TabContainer * node_tabs = cast_to < TabContainer > ( node_dock - > get_parent ( ) ) ;
TabContainer * fs_tabs = cast_to < TabContainer > ( filesystem_dock - > get_parent ( ) ) ;
if ( profile . is_valid ( ) ) {
node_tabs - > set_tab_hidden ( node_dock - > get_index ( ) , profile - > is_feature_disabled ( EditorFeatureProfile : : FEATURE_NODE_DOCK ) ) ;
2020-05-08 21:51:42 +02:00
// The Import dock is useless without the FileSystem dock. Ensure the configuration is valid.
bool fs_dock_disabled = profile - > is_feature_disabled ( EditorFeatureProfile : : FEATURE_FILESYSTEM_DOCK ) ;
fs_tabs - > set_tab_hidden ( filesystem_dock - > get_index ( ) , fs_dock_disabled ) ;
import_tabs - > set_tab_hidden ( import_dock - > get_index ( ) , fs_dock_disabled | | profile - > is_feature_disabled ( EditorFeatureProfile : : FEATURE_IMPORT_DOCK ) ) ;
2019-04-09 00:18:03 +02:00
main_editor_buttons [ EDITOR_3D ] - > set_visible ( ! profile - > is_feature_disabled ( EditorFeatureProfile : : FEATURE_3D ) ) ;
main_editor_buttons [ EDITOR_SCRIPT ] - > set_visible ( ! profile - > is_feature_disabled ( EditorFeatureProfile : : FEATURE_SCRIPT ) ) ;
2022-06-29 19:27:27 +02:00
if ( AssetLibraryEditorPlugin : : is_available ( ) ) {
2019-07-02 15:28:34 +02:00
main_editor_buttons [ EDITOR_ASSETLIB ] - > set_visible ( ! profile - > is_feature_disabled ( EditorFeatureProfile : : FEATURE_ASSET_LIB ) ) ;
2021-05-05 12:44:11 +02:00
}
2019-06-05 06:12:08 +02:00
if ( ( profile - > is_feature_disabled ( EditorFeatureProfile : : FEATURE_3D ) & & singleton - > main_editor_buttons [ EDITOR_3D ] - > is_pressed ( ) ) | |
( profile - > is_feature_disabled ( EditorFeatureProfile : : FEATURE_SCRIPT ) & & singleton - > main_editor_buttons [ EDITOR_SCRIPT ] - > is_pressed ( ) ) | |
2022-06-29 19:27:27 +02:00
( AssetLibraryEditorPlugin : : is_available ( ) & & profile - > is_feature_disabled ( EditorFeatureProfile : : FEATURE_ASSET_LIB ) & & singleton - > main_editor_buttons [ EDITOR_ASSETLIB ] - > is_pressed ( ) ) ) {
2019-04-09 00:18:03 +02:00
_editor_select ( EDITOR_2D ) ;
}
} else {
import_tabs - > set_tab_hidden ( import_dock - > get_index ( ) , false ) ;
node_tabs - > set_tab_hidden ( node_dock - > get_index ( ) , false ) ;
fs_tabs - > set_tab_hidden ( filesystem_dock - > get_index ( ) , false ) ;
import_dock - > set_visible ( true ) ;
node_dock - > set_visible ( true ) ;
filesystem_dock - > set_visible ( true ) ;
main_editor_buttons [ EDITOR_3D ] - > set_visible ( true ) ;
2019-06-05 06:12:08 +02:00
main_editor_buttons [ EDITOR_SCRIPT ] - > set_visible ( true ) ;
2022-06-29 19:27:27 +02:00
if ( AssetLibraryEditorPlugin : : is_available ( ) ) {
2019-07-02 15:28:34 +02:00
main_editor_buttons [ EDITOR_ASSETLIB ] - > set_visible ( true ) ;
2021-05-05 12:44:11 +02:00
}
2019-04-09 00:18:03 +02:00
}
_update_dock_slots_visibility ( ) ;
}
2016-01-18 00:03:57 +01:00
void EditorNode : : _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _menu_option " , & EditorNode : : _menu_option ) ;
2018-03-17 02:50:35 +01:00
ClassDB : : bind_method ( " _tool_menu_option " , & EditorNode : : _tool_menu_option ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _menu_confirm_current " , & EditorNode : : _menu_confirm_current ) ;
ClassDB : : bind_method ( " _dialog_action " , & EditorNode : : _dialog_action ) ;
ClassDB : : bind_method ( " _editor_select " , & EditorNode : : _editor_select ) ;
ClassDB : : bind_method ( " _node_renamed " , & EditorNode : : _node_renamed ) ;
ClassDB : : bind_method ( " edit_node " , & EditorNode : : edit_node ) ;
ClassDB : : bind_method ( " _unhandled_input " , & EditorNode : : _unhandled_input ) ;
2019-04-10 17:21:26 +02:00
ClassDB : : bind_method ( " _update_file_menu_opened " , & EditorNode : : _update_file_menu_opened ) ;
ClassDB : : bind_method ( " _update_file_menu_closed " , & EditorNode : : _update_file_menu_closed ) ;
2021-07-15 15:12:56 +02:00
ClassDB : : bind_method ( " _android_build_source_selected " , & EditorNode : : _android_build_source_selected ) ;
2017-03-05 16:44:50 +01:00
2018-12-31 09:52:09 +01:00
ClassDB : : bind_method ( D_METHOD ( " push_item " , " object " , " property " , " inspector_only " ) , & EditorNode : : push_item , DEFVAL ( " " ) , DEFVAL ( false ) ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _get_scene_metadata " , & EditorNode : : _get_scene_metadata ) ;
ClassDB : : bind_method ( " set_edited_scene " , & EditorNode : : set_edited_scene ) ;
ClassDB : : bind_method ( " open_request " , & EditorNode : : open_request ) ;
2019-05-08 04:35:23 +02:00
ClassDB : : bind_method ( " _inherit_request " , & EditorNode : : _inherit_request ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _instance_request " , & EditorNode : : _instance_request ) ;
ClassDB : : bind_method ( " _close_messages " , & EditorNode : : _close_messages ) ;
ClassDB : : bind_method ( " _show_messages " , & EditorNode : : _show_messages ) ;
ClassDB : : bind_method ( " _vp_resized " , & EditorNode : : _vp_resized ) ;
2019-12-24 01:20:54 +01:00
ClassDB : : bind_method ( " _version_button_pressed " , & EditorNode : : _version_button_pressed ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _quick_opened " , & EditorNode : : _quick_opened ) ;
ClassDB : : bind_method ( " _quick_run " , & EditorNode : : _quick_run ) ;
ClassDB : : bind_method ( " _open_recent_scene " , & EditorNode : : _open_recent_scene ) ;
ClassDB : : bind_method ( " stop_child_process " , & EditorNode : : stop_child_process ) ;
2018-06-30 05:08:28 +02:00
ClassDB : : bind_method ( " get_script_create_dialog " , & EditorNode : : get_script_create_dialog ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _sources_changed " , & EditorNode : : _sources_changed ) ;
ClassDB : : bind_method ( " _fs_changed " , & EditorNode : : _fs_changed ) ;
ClassDB : : bind_method ( " _dock_select_draw " , & EditorNode : : _dock_select_draw ) ;
ClassDB : : bind_method ( " _dock_select_input " , & EditorNode : : _dock_select_input ) ;
ClassDB : : bind_method ( " _dock_pre_popup " , & EditorNode : : _dock_pre_popup ) ;
ClassDB : : bind_method ( " _dock_split_dragged " , & EditorNode : : _dock_split_dragged ) ;
ClassDB : : bind_method ( " _save_docks " , & EditorNode : : _save_docks ) ;
ClassDB : : bind_method ( " _dock_popup_exit " , & EditorNode : : _dock_popup_exit ) ;
ClassDB : : bind_method ( " _dock_move_left " , & EditorNode : : _dock_move_left ) ;
ClassDB : : bind_method ( " _dock_move_right " , & EditorNode : : _dock_move_right ) ;
2018-02-07 14:01:45 +01:00
ClassDB : : bind_method ( " _dock_tab_changed " , & EditorNode : : _dock_tab_changed ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _layout_menu_option " , & EditorNode : : _layout_menu_option ) ;
ClassDB : : bind_method ( " set_current_scene " , & EditorNode : : set_current_scene ) ;
ClassDB : : bind_method ( " set_current_version " , & EditorNode : : set_current_version ) ;
ClassDB : : bind_method ( " _scene_tab_changed " , & EditorNode : : _scene_tab_changed ) ;
ClassDB : : bind_method ( " _scene_tab_closed " , & EditorNode : : _scene_tab_closed ) ;
2017-06-15 17:30:03 +02:00
ClassDB : : bind_method ( " _scene_tab_hover " , & EditorNode : : _scene_tab_hover ) ;
ClassDB : : bind_method ( " _scene_tab_exit " , & EditorNode : : _scene_tab_exit ) ;
ClassDB : : bind_method ( " _scene_tab_input " , & EditorNode : : _scene_tab_input ) ;
2017-07-05 15:44:53 +02:00
ClassDB : : bind_method ( " _reposition_active_tab " , & EditorNode : : _reposition_active_tab ) ;
2017-06-15 17:30:03 +02:00
ClassDB : : bind_method ( " _thumbnail_done " , & EditorNode : : _thumbnail_done ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _scene_tab_script_edited " , & EditorNode : : _scene_tab_script_edited ) ;
ClassDB : : bind_method ( " _set_main_scene_state " , & EditorNode : : _set_main_scene_state ) ;
ClassDB : : bind_method ( " _update_scene_tabs " , & EditorNode : : _update_scene_tabs ) ;
2017-06-21 06:15:39 +02:00
ClassDB : : bind_method ( " _discard_changes " , & EditorNode : : _discard_changes ) ;
2017-10-12 04:35:15 +02:00
ClassDB : : bind_method ( " _update_recent_scenes " , & EditorNode : : _update_recent_scenes ) ;
2021-07-06 16:10:07 +02:00
ClassDB : : bind_method ( " _pick_main_scene_custom_action " , & EditorNode : : _pick_main_scene_custom_action ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _clear_undo_history " , & EditorNode : : _clear_undo_history ) ;
ClassDB : : bind_method ( " _dropped_files " , & EditorNode : : _dropped_files ) ;
2019-02-06 14:57:06 +01:00
ClassDB : : bind_method ( D_METHOD ( " _global_menu_action " ) , & EditorNode : : _global_menu_action , DEFVAL ( Variant ( ) ) ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( " _toggle_distraction_free_mode " , & EditorNode : : _toggle_distraction_free_mode ) ;
2019-09-03 16:42:08 +02:00
ClassDB : : bind_method ( " _version_control_menu_option " , & EditorNode : : _version_control_menu_option ) ;
2019-02-22 21:42:29 +01:00
ClassDB : : bind_method ( " edit_item_resource " , & EditorNode : : edit_item_resource ) ;
2017-09-14 15:38:59 +02:00
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_gui_base " ) , & EditorNode : : get_gui_base ) ;
ClassDB : : bind_method ( D_METHOD ( " _bottom_panel_switch " ) , & EditorNode : : _bottom_panel_switch ) ;
2016-01-18 00:03:57 +01:00
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " _open_imported " ) , & EditorNode : : _open_imported ) ;
ClassDB : : bind_method ( D_METHOD ( " _inherit_imported " ) , & EditorNode : : _inherit_imported ) ;
2016-01-18 00:03:57 +01:00
2019-07-09 20:11:31 +02:00
ClassDB : : bind_method ( " _copy_warning " , & EditorNode : : _copy_warning ) ;
2017-08-31 23:57:03 +02:00
ClassDB : : bind_method ( D_METHOD ( " _resources_reimported " ) , & EditorNode : : _resources_reimported ) ;
2018-07-16 03:38:14 +02:00
ClassDB : : bind_method ( D_METHOD ( " _bottom_panel_raise_toggled " ) , & EditorNode : : _bottom_panel_raise_toggled ) ;
2017-08-31 23:57:03 +02:00
2018-07-19 17:34:22 +02:00
ClassDB : : bind_method ( D_METHOD ( " _on_plugin_ready " ) , & EditorNode : : _on_plugin_ready ) ;
2018-07-19 23:58:15 +02:00
ClassDB : : bind_method ( D_METHOD ( " _video_driver_selected " ) , & EditorNode : : _video_driver_selected ) ;
2018-11-21 01:47:48 +01:00
ClassDB : : bind_method ( D_METHOD ( " _resources_changed " ) , & EditorNode : : _resources_changed ) ;
2021-02-11 01:08:49 +01:00
ClassDB : : bind_method ( D_METHOD ( " _reload_modified_scenes " ) , & EditorNode : : _reload_modified_scenes ) ;
ClassDB : : bind_method ( D_METHOD ( " _reload_project_settings " ) , & EditorNode : : _reload_project_settings ) ;
ClassDB : : bind_method ( D_METHOD ( " _resave_scenes " ) , & EditorNode : : _resave_scenes ) ;
2022-03-28 04:49:13 +02:00
ClassDB : : bind_method ( D_METHOD ( " _project_settings_changed " ) , & EditorNode : : _project_settings_changed ) ;
2019-04-09 00:18:03 +02:00
ClassDB : : bind_method ( D_METHOD ( " _feature_profile_changed " ) , & EditorNode : : _feature_profile_changed ) ;
2018-11-21 01:47:48 +01:00
2019-03-29 14:53:11 +01:00
ClassDB : : bind_method ( " _screenshot " , & EditorNode : : _screenshot ) ;
ClassDB : : bind_method ( " _request_screenshot " , & EditorNode : : _request_screenshot ) ;
ClassDB : : bind_method ( " _save_screenshot " , & EditorNode : : _save_screenshot ) ;
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " play_pressed " ) ) ;
ADD_SIGNAL ( MethodInfo ( " pause_pressed " ) ) ;
ADD_SIGNAL ( MethodInfo ( " stop_pressed " ) ) ;
2017-05-16 21:26:32 +02:00
ADD_SIGNAL ( MethodInfo ( " request_help_search " ) ) ;
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " script_add_function_request " , PropertyInfo ( Variant : : OBJECT , " obj " ) , PropertyInfo ( Variant : : STRING , " function " ) , PropertyInfo ( Variant : : POOL_STRING_ARRAY , " args " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " resource_saved " , PropertyInfo ( Variant : : OBJECT , " obj " ) ) ) ;
2021-12-04 01:12:52 +01:00
ADD_SIGNAL ( MethodInfo ( " scene_saved " , PropertyInfo ( Variant : : STRING , " path " ) ) ) ;
2016-01-18 00:03:57 +01:00
}
2017-03-05 16:44:50 +01:00
static Node * _resource_get_edited_scene ( ) {
2017-01-10 05:04:31 +01:00
return EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ;
}
2017-11-14 23:02:31 +01:00
void EditorNode : : _print_handler ( void * p_this , const String & p_string , bool p_error ) {
EditorNode * en = ( EditorNode * ) p_this ;
2018-08-13 17:04:38 +02:00
en - > log - > add_message ( p_string , p_error ? EditorLog : : MSG_TYPE_ERROR : EditorLog : : MSG_TYPE_STD ) ;
2017-11-14 23:02:31 +01:00
}
2019-04-07 20:46:52 +02:00
static void _execute_thread ( void * p_ud ) {
EditorNode : : ExecuteThreadArgs * eta = ( EditorNode : : ExecuteThreadArgs * ) p_ud ;
2021-05-04 16:00:45 +02:00
Error err = OS : : get_singleton ( ) - > execute ( eta - > path , eta - > args , true , nullptr , & eta - > output , & eta - > exitcode , true , & eta - > execute_output_mutex ) ;
2019-04-07 20:46:52 +02:00
print_verbose ( " Thread exit status: " + itos ( eta - > exitcode ) ) ;
if ( err ! = OK ) {
eta - > exitcode = err ;
}
2021-01-31 13:34:42 +01:00
eta - > done . set ( ) ;
2019-04-07 20:46:52 +02:00
}
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 ) {
execute_output_dialog - > set_title ( p_title ) ;
execute_output_dialog - > get_ok ( ) - > set_disabled ( true ) ;
execute_outputs - > clear ( ) ;
execute_outputs - > set_scroll_follow ( true ) ;
execute_output_dialog - > popup_centered_ratio ( ) ;
ExecuteThreadArgs eta ;
eta . path = p_path ;
eta . args = p_arguments ;
eta . exitcode = 255 ;
int prev_len = 0 ;
2021-01-27 20:10:10 +01:00
eta . execute_output_thread . start ( _execute_thread , & eta ) ;
2019-04-07 20:46:52 +02:00
2021-01-31 13:34:42 +01:00
while ( ! eta . done . is_set ( ) ) {
2021-01-27 10:43:02 +01:00
eta . execute_output_mutex . lock ( ) ;
2019-04-07 20:46:52 +02:00
if ( prev_len ! = eta . output . length ( ) ) {
String to_add = eta . output . substr ( prev_len , eta . output . length ( ) ) ;
prev_len = eta . output . length ( ) ;
execute_outputs - > add_text ( to_add ) ;
Main : : iteration ( ) ;
}
2021-01-27 10:43:02 +01:00
eta . execute_output_mutex . unlock ( ) ;
2019-04-07 20:46:52 +02:00
OS : : get_singleton ( ) - > delay_usec ( 1000 ) ;
}
2021-01-27 20:10:10 +01:00
eta . execute_output_thread . wait_to_finish ( ) ;
2019-04-07 20:46:52 +02:00
execute_outputs - > add_text ( " \n Exit Code: " + itos ( eta . exitcode ) ) ;
if ( p_close_on_errors & & eta . exitcode ! = 0 ) {
execute_output_dialog - > hide ( ) ;
}
if ( p_close_on_ok & & eta . exitcode = = 0 ) {
execute_output_dialog - > hide ( ) ;
}
execute_output_dialog - > get_ok ( ) - > set_disabled ( false ) ;
return eta . exitcode ;
}
2014-02-10 02:10:30 +01:00
EditorNode : : EditorNode ( ) {
2023-01-22 19:42:34 +01:00
OS : : get_singleton ( ) - > benchmark_begin_measure ( " editor " ) ;
2022-02-28 13:06:31 +01:00
EditorPropertyNameProcessor * epnp = memnew ( EditorPropertyNameProcessor ) ;
add_child ( epnp ) ;
2019-03-03 23:52:18 +01:00
Input : : get_singleton ( ) - > set_use_accumulated_input ( true ) ;
2017-03-05 16:44:50 +01:00
Resource : : _get_local_scene_func = _resource_get_edited_scene ;
2017-01-10 05:04:31 +01:00
2016-12-23 04:37:38 +01:00
VisualServer : : get_singleton ( ) - > textures_keep_original ( true ) ;
2017-06-11 20:52:03 +02:00
VisualServer : : get_singleton ( ) - > set_debug_generate_wireframes ( true ) ;
2016-12-23 04:37:38 +01:00
2021-12-16 06:15:23 +01:00
NavigationServer : : get_singleton ( ) - > set_active ( false ) ; // no nav by default if editor
2018-08-21 02:55:01 +02:00
PhysicsServer : : get_singleton ( ) - > set_active ( false ) ; // no physics by default if editor
Physics2DServer : : get_singleton ( ) - > set_active ( false ) ; // no physics by default if editor
ScriptServer : : set_scripting_enabled ( false ) ; // no scripting by default if editor
2018-09-13 03:38:39 +02:00
EditorHelp : : generate_doc ( ) ; //before any editor classes are created
2015-10-17 00:11:23 +02:00
SceneState : : set_disable_placeholders ( true ) ;
2017-06-28 22:00:18 +02:00
ResourceLoader : : clear_translation_remaps ( ) ; //no remaps using during editor
2017-12-14 19:33:54 +01:00
ResourceLoader : : clear_path_remaps ( ) ;
2014-02-10 02:10:30 +01:00
2017-08-24 22:58:51 +02:00
InputDefault * id = Object : : cast_to < InputDefault > ( Input : : get_singleton ( ) ) ;
2015-09-24 23:06:15 +02:00
if ( id ) {
if ( ! OS : : get_singleton ( ) - > has_touchscreen_ui_hint ( ) & & Input : : get_singleton ( ) ) {
//only if no touchscreen ui hint, set emulation
2018-02-24 03:04:30 +01:00
id - > set_emulate_touch_from_mouse ( false ) ; //just disable just in case
2015-09-24 23:06:15 +02:00
}
id - > set_custom_mouse_cursor ( RES ( ) ) ;
2015-08-29 22:16:11 +02:00
}
2017-03-05 16:44:50 +01:00
singleton = this ;
exiting = false ;
2019-10-31 20:58:53 +01:00
dimmed = false ;
2017-03-05 16:44:50 +01:00
last_checked_version = 0 ;
changing_scene = false ;
_initializing_addons = false ;
2016-05-30 20:29:43 +02:00
docks_visible = true ;
2017-11-25 00:32:54 +01:00
restoring_scenes = false ;
2020-01-14 11:32:15 +01:00
cmdline_export_mode = false ;
2017-04-25 13:48:35 +02:00
scene_distraction = false ;
script_distraction = false ;
2014-02-10 02:10:30 +01:00
TranslationServer : : get_singleton ( ) - > set_enabled ( false ) ;
// load settings
2021-05-05 12:44:11 +02:00
if ( ! EditorSettings : : get_singleton ( ) ) {
2014-02-10 02:10:30 +01:00
EditorSettings : : create ( ) ;
2021-05-05 12:44:11 +02:00
}
2016-09-13 16:20:09 +02:00
2018-01-12 21:18:40 +01:00
FileAccess : : set_backup_save ( EDITOR_GET ( " filesystem/on_save/safe_save_on_backup_then_rename " ) ) ;
2016-06-05 23:43:45 +02:00
{
2018-03-22 20:20:42 +01:00
int display_scale = EditorSettings : : get_singleton ( ) - > get ( " interface/editor/display_scale " ) ;
switch ( display_scale ) {
2021-05-09 23:33:45 +02:00
case 0 :
2020-11-17 11:17:41 +01:00
// Try applying a suitable display scale automatically.
2021-05-09 23:33:45 +02:00
editor_set_scale ( EditorSettings : : get_singleton ( ) - > get_auto_display_scale ( ) ) ;
break ;
2020-11-17 11:17:41 +01:00
case 1 :
2018-03-22 20:20:42 +01:00
editor_set_scale ( 0.75 ) ;
2020-11-17 11:17:41 +01:00
break ;
case 2 :
2018-03-22 20:20:42 +01:00
editor_set_scale ( 1.0 ) ;
2020-11-17 11:17:41 +01:00
break ;
case 3 :
2018-03-22 20:20:42 +01:00
editor_set_scale ( 1.25 ) ;
2020-11-17 11:17:41 +01:00
break ;
case 4 :
2018-03-22 20:20:42 +01:00
editor_set_scale ( 1.5 ) ;
2020-11-17 11:17:41 +01:00
break ;
case 5 :
2018-03-22 20:20:42 +01:00
editor_set_scale ( 1.75 ) ;
2020-11-17 11:17:41 +01:00
break ;
case 6 :
2018-03-22 20:20:42 +01:00
editor_set_scale ( 2.0 ) ;
2020-11-17 11:17:41 +01:00
break ;
default :
editor_set_scale ( EditorSettings : : get_singleton ( ) - > get ( " interface/editor/custom_display_scale " ) ) ;
break ;
2016-06-05 23:43:45 +02:00
}
}
2019-08-17 21:56:59 +02:00
// Define a minimum window size to prevent UI elements from overlapping or being cut off
OS : : get_singleton ( ) - > set_min_window_size ( Size2 ( 1024 , 600 ) * EDSCALE ) ;
2017-01-05 23:41:36 +01:00
FileDialog : : set_default_show_hidden_files ( EditorSettings : : get_singleton ( ) - > get ( " filesystem/file_dialog/show_hidden_files " ) ) ;
EditorFileDialog : : set_default_show_hidden_files ( EditorSettings : : get_singleton ( ) - > get ( " filesystem/file_dialog/show_hidden_files " ) ) ;
EditorFileDialog : : set_default_display_mode ( ( EditorFileDialog : : DisplayMode ) EditorSettings : : get_singleton ( ) - > get ( " filesystem/file_dialog/display_mode " ) . operator int ( ) ) ;
2022-03-21 10:55:18 +01:00
int swap_cancel_ok = EDITOR_GET ( " interface/editor/accept_dialog_cancel_ok_buttons " ) ;
if ( swap_cancel_ok ! = 0 ) { // 0 is auto, set in register_scene based on OS.
// Swap on means OK first.
AcceptDialog : : set_swap_ok_cancel ( swap_cancel_ok = = 2 ) ;
}
ResourceLoader : : set_abort_on_missing_resources ( false ) ;
2017-03-05 16:44:50 +01:00
ResourceLoader : : set_error_notify_func ( this , _load_error_notify ) ;
ResourceLoader : : set_dependency_error_notify_func ( this , _dependency_error_report ) ;
2014-02-10 02:10:30 +01:00
2017-03-24 21:45:31 +01:00
{ //register importers at the beginning, so dialogs are created with the right extensions
2017-02-01 13:45:45 +01:00
Ref < ResourceImporterTexture > import_texture ;
import_texture . instance ( ) ;
ResourceFormatImporter : : get_singleton ( ) - > add_importer ( import_texture ) ;
2017-02-02 00:41:05 +01:00
2018-08-06 19:56:06 +02:00
Ref < ResourceImporterLayeredTexture > import_3d ;
import_3d . instance ( ) ;
import_3d - > set_3d ( true ) ;
ResourceFormatImporter : : get_singleton ( ) - > add_importer ( import_3d ) ;
Ref < ResourceImporterLayeredTexture > import_array ;
import_array . instance ( ) ;
import_array - > set_3d ( false ) ;
ResourceFormatImporter : : get_singleton ( ) - > add_importer ( import_array ) ;
2018-07-29 21:45:23 +02:00
Ref < ResourceImporterImage > import_image ;
import_image . instance ( ) ;
ResourceFormatImporter : : get_singleton ( ) - > add_importer ( import_image ) ;
2019-04-19 20:54:33 +02:00
Ref < ResourceImporterTextureAtlas > import_texture_atlas ;
import_texture_atlas . instance ( ) ;
ResourceFormatImporter : : get_singleton ( ) - > add_importer ( import_texture_atlas ) ;
2017-02-02 00:41:05 +01:00
Ref < ResourceImporterCSVTranslation > import_csv_translation ;
import_csv_translation . instance ( ) ;
ResourceFormatImporter : : get_singleton ( ) - > add_importer ( import_csv_translation ) ;
2017-02-03 02:51:26 +01:00
Ref < ResourceImporterWAV > import_wav ;
import_wav . instance ( ) ;
ResourceFormatImporter : : get_singleton ( ) - > add_importer ( import_wav ) ;
2017-09-30 01:38:27 +02:00
Ref < ResourceImporterOBJ > import_obj ;
import_obj . instance ( ) ;
ResourceFormatImporter : : get_singleton ( ) - > add_importer ( import_obj ) ;
2017-02-04 13:48:04 +01:00
Ref < ResourceImporterScene > import_scene ;
import_scene . instance ( ) ;
ResourceFormatImporter : : get_singleton ( ) - > add_importer ( import_scene ) ;
{
Ref < EditorSceneImporterCollada > import_collada ;
import_collada . instance ( ) ;
import_scene - > add_importer ( import_collada ) ;
2017-07-18 02:05:38 +02:00
2019-02-12 21:10:08 +01:00
Ref < EditorOBJImporter > import_obj2 ;
import_obj2 . instance ( ) ;
import_scene - > add_importer ( import_obj2 ) ;
2017-08-02 20:34:55 +02:00
2018-01-30 15:03:46 +01:00
Ref < EditorSceneImporterESCN > import_escn ;
import_escn . instance ( ) ;
import_scene - > add_importer ( import_escn ) ;
2017-02-04 13:48:04 +01:00
}
2018-01-06 20:36:49 +01:00
Ref < ResourceImporterBitMap > import_bitmap ;
import_bitmap . instance ( ) ;
ResourceFormatImporter : : get_singleton ( ) - > add_importer ( import_bitmap ) ;
2017-02-01 13:45:45 +01:00
}
2018-05-15 22:12:35 +02:00
{
Ref < EditorInspectorDefaultPlugin > eidp ;
eidp . instance ( ) ;
EditorInspector : : add_inspector_plugin ( eidp ) ;
2018-06-27 00:05:11 +02:00
Ref < EditorInspectorRootMotionPlugin > rmp ;
rmp . instance ( ) ;
EditorInspector : : add_inspector_plugin ( rmp ) ;
2018-07-14 23:15:42 +02:00
Ref < EditorInspectorShaderModePlugin > smp ;
smp . instance ( ) ;
EditorInspector : : add_inspector_plugin ( smp ) ;
2018-05-15 22:12:35 +02:00
}
2017-03-05 16:44:50 +01:00
editor_selection = memnew ( EditorSelection ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
EditorFileSystem * efs = memnew ( EditorFileSystem ) ;
2014-02-10 02:10:30 +01:00
add_child ( efs ) ;
//used for previews
2017-03-05 16:44:50 +01:00
FileDialog : : get_icon_func = _file_dialog_get_icon ;
FileDialog : : register_func = _file_dialog_register ;
FileDialog : : unregister_func = _file_dialog_unregister ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
EditorFileDialog : : get_icon_func = _file_dialog_get_icon ;
EditorFileDialog : : register_func = _editor_file_dialog_register ;
EditorFileDialog : : unregister_func = _editor_file_dialog_unregister ;
2015-05-31 06:59:42 +02:00
2017-03-05 16:44:50 +01:00
editor_export = memnew ( EditorExport ) ;
2017-02-20 03:19:30 +01:00
add_child ( editor_export ) ;
2019-10-11 13:21:24 +02:00
// Exporters might need the theme
theme = create_custom_theme ( ) ;
2014-02-10 02:10:30 +01:00
register_exporters ( ) ;
2018-06-27 00:05:11 +02:00
ClassDB : : set_class_enabled ( " RootMotionView " , true ) ;
2014-02-10 02:10:30 +01:00
2018-05-17 23:02:16 +02:00
//defs here, use EDITOR_GET in logic
2018-07-19 23:58:15 +02:00
EDITOR_DEF_RST ( " interface/scene_tabs/always_show_close_button " , false ) ;
EDITOR_DEF_RST ( " interface/scene_tabs/resize_if_many_tabs " , true ) ;
EDITOR_DEF_RST ( " interface/scene_tabs/minimum_width " , 50 ) ;
2018-05-17 23:02:16 +02:00
EDITOR_DEF ( " run/output/always_clear_output_on_play " , true ) ;
EDITOR_DEF ( " run/output/always_open_output_on_play " , true ) ;
EDITOR_DEF ( " run/output/always_close_output_on_stop " , true ) ;
2021-04-11 15:39:31 +02:00
EDITOR_DEF ( " interface/editor/save_on_focus_loss " , false ) ;
2018-07-19 23:58:15 +02:00
EDITOR_DEF_RST ( " interface/editor/save_each_scene_on_quit " , true ) ;
2018-05-17 23:02:16 +02:00
EDITOR_DEF ( " interface/editor/quit_confirmation " , true ) ;
2018-12-11 16:52:25 +01:00
EDITOR_DEF ( " interface/editor/update_continuously " , false ) ;
2023-02-09 11:28:22 +01:00
# if defined(ANDROID_ENABLED) || defined(JAVASCRIPT_ENABLED)
EDITOR_DEF ( " interface/editor/show_update_spinner " , true ) ;
EDITOR_DEF ( " interface/editor/update_vital_only " , true ) ;
# else
EDITOR_DEF ( " interface/editor/show_update_spinner " , false ) ;
2021-10-05 20:05:57 +02:00
EDITOR_DEF ( " interface/editor/update_vital_only " , false ) ;
2023-02-09 11:28:22 +01:00
# endif
2022-03-19 12:04:49 +01:00
EDITOR_DEF ( " interface/editor/localize_settings " , true ) ;
2018-07-19 23:58:15 +02:00
EDITOR_DEF_RST ( " interface/scene_tabs/restore_scenes_on_load " , false ) ;
EDITOR_DEF_RST ( " interface/scene_tabs/show_thumbnail_on_hover " , true ) ;
2022-03-19 12:04:49 +01:00
EDITOR_DEF_RST ( " interface/inspector/default_property_name_style " , EditorPropertyNameProcessor : : STYLE_CAPITALIZED ) ;
EditorSettings : : get_singleton ( ) - > add_property_hint ( PropertyInfo ( Variant : : INT , " interface/inspector/default_property_name_style " , PROPERTY_HINT_ENUM , " Raw,Capitalized,Localized " ) ) ;
2019-07-23 17:27:55 +02:00
EDITOR_DEF_RST ( " interface/inspector/default_float_step " , 0.001 ) ;
2020-02-10 04:50:11 +01:00
EditorSettings : : get_singleton ( ) - > add_property_hint ( PropertyInfo ( Variant : : REAL , " interface/inspector/default_float_step " , PROPERTY_HINT_RANGE , " 0,1,0 " ) ) ;
2018-07-19 23:58:15 +02:00
EDITOR_DEF_RST ( " interface/inspector/disable_folding " , false ) ;
2018-11-25 14:46:26 +01:00
EDITOR_DEF_RST ( " interface/inspector/auto_unfold_foreign_scenes " , true ) ;
2018-08-07 17:19:19 +02:00
EDITOR_DEF ( " interface/inspector/horizontal_vector2_editing " , false ) ;
2018-09-23 05:20:36 +02:00
EDITOR_DEF ( " interface/inspector/horizontal_vector_types_editing " , true ) ;
2018-07-14 23:15:42 +02:00
EDITOR_DEF ( " interface/inspector/open_resources_in_current_inspector " , true ) ;
2021-02-13 00:34:28 +01:00
EDITOR_DEF ( " interface/inspector/resources_to_open_in_new_inspector " , " Script,MeshLibrary,TileSet " ) ;
2019-08-30 22:25:15 +02:00
EDITOR_DEF ( " interface/inspector/default_color_picker_mode " , 0 ) ;
EditorSettings : : get_singleton ( ) - > add_property_hint ( PropertyInfo ( Variant : : INT , " interface/inspector/default_color_picker_mode " , PROPERTY_HINT_ENUM , " RGB,HSV,RAW " , PROPERTY_USAGE_DEFAULT ) ) ;
2020-06-25 11:59:31 +02:00
EDITOR_DEF ( " version_control/username " , " " ) ;
EDITOR_DEF ( " version_control/ssh_public_key_path " , " " ) ;
EditorSettings : : get_singleton ( ) - > add_property_hint ( PropertyInfo ( Variant : : STRING , " version_control/ssh_public_key_path " , PROPERTY_HINT_GLOBAL_FILE ) ) ;
EDITOR_DEF ( " version_control/ssh_private_key_path " , " " ) ;
EditorSettings : : get_singleton ( ) - > add_property_hint ( PropertyInfo ( Variant : : STRING , " version_control/ssh_private_key_path " , PROPERTY_HINT_GLOBAL_FILE ) ) ;
2018-05-17 23:02:16 +02:00
2017-05-02 22:13:12 +02:00
theme_base = memnew ( Control ) ;
2016-06-17 06:13:23 +02:00
add_child ( theme_base ) ;
2017-09-22 00:12:33 +02:00
theme_base - > set_anchors_and_margins_preset ( Control : : PRESET_WIDE ) ;
2016-06-17 06:13:23 +02:00
2017-03-05 16:44:50 +01:00
gui_base = memnew ( Panel ) ;
2016-06-17 06:13:23 +02:00
theme_base - > add_child ( gui_base ) ;
2017-09-22 00:12:33 +02:00
gui_base - > set_anchors_and_margins_preset ( Control : : PRESET_WIDE ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
theme_base - > set_theme ( theme ) ;
2017-11-11 18:57:54 +01:00
gui_base - > set_theme ( theme ) ;
2017-05-02 22:13:12 +02:00
gui_base - > add_style_override ( " panel " , gui_base - > get_stylebox ( " Background " , " EditorStyles " ) ) ;
2016-06-17 06:13:23 +02:00
2017-03-05 16:44:50 +01:00
resource_preview = memnew ( EditorResourcePreview ) ;
2015-05-31 06:59:42 +02:00
add_child ( resource_preview ) ;
2017-03-05 16:44:50 +01:00
progress_dialog = memnew ( ProgressDialog ) ;
2014-02-10 02:10:30 +01:00
gui_base - > add_child ( progress_dialog ) ;
// take up all screen
2017-03-05 16:44:50 +01:00
gui_base - > set_anchor ( MARGIN_RIGHT , Control : : ANCHOR_END ) ;
gui_base - > set_anchor ( MARGIN_BOTTOM , Control : : ANCHOR_END ) ;
gui_base - > set_end ( Point2 ( 0 , 0 ) ) ;
2015-06-22 05:03:19 +02:00
2017-03-05 16:44:50 +01:00
main_vbox = memnew ( VBoxContainer ) ;
2014-02-10 02:10:30 +01:00
gui_base - > add_child ( main_vbox ) ;
2017-09-22 00:12:33 +02:00
main_vbox - > set_anchors_and_margins_preset ( Control : : PRESET_WIDE , Control : : PRESET_MODE_MINSIZE , 8 ) ;
2019-02-20 16:08:52 +01:00
main_vbox - > add_constant_override ( " separation " , 8 * EDSCALE ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
menu_hb = memnew ( HBoxContainer ) ;
2015-11-18 08:47:41 +01:00
main_vbox - > add_child ( menu_hb ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
left_l_hsplit = memnew ( HSplitContainer ) ;
2015-06-14 03:12:53 +02:00
main_vbox - > add_child ( left_l_hsplit ) ;
left_l_hsplit - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2017-03-05 16:44:50 +01:00
left_l_vsplit = memnew ( VSplitContainer ) ;
2015-06-14 03:12:53 +02:00
left_l_hsplit - > add_child ( left_l_vsplit ) ;
2017-03-05 16:44:50 +01:00
dock_slot [ DOCK_SLOT_LEFT_UL ] = memnew ( TabContainer ) ;
2015-06-14 03:12:53 +02:00
left_l_vsplit - > add_child ( dock_slot [ DOCK_SLOT_LEFT_UL ] ) ;
2017-03-05 16:44:50 +01:00
dock_slot [ DOCK_SLOT_LEFT_BL ] = memnew ( TabContainer ) ;
2015-06-14 03:12:53 +02:00
left_l_vsplit - > add_child ( dock_slot [ DOCK_SLOT_LEFT_BL ] ) ;
2017-03-05 16:44:50 +01:00
left_r_hsplit = memnew ( HSplitContainer ) ;
2015-06-14 03:12:53 +02:00
left_l_hsplit - > add_child ( left_r_hsplit ) ;
2017-03-05 16:44:50 +01:00
left_r_vsplit = memnew ( VSplitContainer ) ;
2015-06-14 03:12:53 +02:00
left_r_hsplit - > add_child ( left_r_vsplit ) ;
2017-03-05 16:44:50 +01:00
dock_slot [ DOCK_SLOT_LEFT_UR ] = memnew ( TabContainer ) ;
2015-06-14 03:12:53 +02:00
left_r_vsplit - > add_child ( dock_slot [ DOCK_SLOT_LEFT_UR ] ) ;
2017-03-05 16:44:50 +01:00
dock_slot [ DOCK_SLOT_LEFT_BR ] = memnew ( TabContainer ) ;
2015-06-14 03:12:53 +02:00
left_r_vsplit - > add_child ( dock_slot [ DOCK_SLOT_LEFT_BR ] ) ;
2017-03-05 16:44:50 +01:00
main_hsplit = memnew ( HSplitContainer ) ;
2015-06-14 03:12:53 +02:00
left_r_hsplit - > add_child ( main_hsplit ) ;
2017-03-05 16:44:50 +01:00
VBoxContainer * center_vb = memnew ( VBoxContainer ) ;
2015-11-18 08:47:41 +01:00
main_hsplit - > add_child ( center_vb ) ;
center_vb - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2015-06-14 03:12:53 +02:00
2017-03-05 16:44:50 +01:00
center_split = memnew ( VSplitContainer ) ;
2015-11-18 08:47:41 +01:00
center_split - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2015-06-14 03:12:53 +02:00
center_split - > set_collapsed ( false ) ;
2015-11-18 08:47:41 +01:00
center_vb - > add_child ( center_split ) ;
2015-06-14 03:12:53 +02:00
2017-03-05 16:44:50 +01:00
right_hsplit = memnew ( HSplitContainer ) ;
2015-06-14 03:12:53 +02:00
main_hsplit - > add_child ( right_hsplit ) ;
2017-03-05 16:44:50 +01:00
right_l_vsplit = memnew ( VSplitContainer ) ;
2015-06-14 03:12:53 +02:00
right_hsplit - > add_child ( right_l_vsplit ) ;
2017-03-05 16:44:50 +01:00
dock_slot [ DOCK_SLOT_RIGHT_UL ] = memnew ( TabContainer ) ;
2015-06-14 03:12:53 +02:00
right_l_vsplit - > add_child ( dock_slot [ DOCK_SLOT_RIGHT_UL ] ) ;
2017-03-05 16:44:50 +01:00
dock_slot [ DOCK_SLOT_RIGHT_BL ] = memnew ( TabContainer ) ;
2015-06-14 03:12:53 +02:00
right_l_vsplit - > add_child ( dock_slot [ DOCK_SLOT_RIGHT_BL ] ) ;
2017-03-05 16:44:50 +01:00
right_r_vsplit = memnew ( VSplitContainer ) ;
2015-06-14 03:12:53 +02:00
right_hsplit - > add_child ( right_r_vsplit ) ;
2017-03-05 16:44:50 +01:00
dock_slot [ DOCK_SLOT_RIGHT_UR ] = memnew ( TabContainer ) ;
2015-06-14 03:12:53 +02:00
right_r_vsplit - > add_child ( dock_slot [ DOCK_SLOT_RIGHT_UR ] ) ;
2017-03-05 16:44:50 +01:00
dock_slot [ DOCK_SLOT_RIGHT_BR ] = memnew ( TabContainer ) ;
2015-06-14 03:12:53 +02:00
right_r_vsplit - > add_child ( dock_slot [ DOCK_SLOT_RIGHT_BR ] ) ;
2018-09-14 16:56:18 +02:00
// Store them for easier access
vsplits . push_back ( left_l_vsplit ) ;
vsplits . push_back ( left_r_vsplit ) ;
vsplits . push_back ( right_l_vsplit ) ;
vsplits . push_back ( right_r_vsplit ) ;
hsplits . push_back ( left_l_hsplit ) ;
hsplits . push_back ( left_r_hsplit ) ;
hsplits . push_back ( main_hsplit ) ;
hsplits . push_back ( right_hsplit ) ;
2015-06-22 05:03:19 +02:00
2018-09-14 16:56:18 +02:00
for ( int i = 0 ; i < vsplits . size ( ) ; i + + ) {
vsplits [ i ] - > connect ( " dragged " , this , " _dock_split_dragged " ) ;
hsplits [ i ] - > connect ( " dragged " , this , " _dock_split_dragged " ) ;
}
2015-06-22 05:03:19 +02:00
2017-07-18 15:04:20 +02:00
dock_select_popup = memnew ( PopupPanel ) ;
gui_base - > add_child ( dock_select_popup ) ;
2017-03-05 16:44:50 +01:00
VBoxContainer * dock_vb = memnew ( VBoxContainer ) ;
2017-07-18 15:04:20 +02:00
dock_select_popup - > add_child ( dock_vb ) ;
2015-06-14 03:12:53 +02:00
2017-03-05 16:44:50 +01:00
HBoxContainer * dock_hb = memnew ( HBoxContainer ) ;
dock_tab_move_left = memnew ( ToolButton ) ;
dock_tab_move_left - > set_icon ( theme - > get_icon ( " Back " , " EditorIcons " ) ) ;
2015-06-14 03:12:53 +02:00
dock_tab_move_left - > set_focus_mode ( Control : : FOCUS_NONE ) ;
2017-03-05 16:44:50 +01:00
dock_tab_move_left - > connect ( " pressed " , this , " _dock_move_left " ) ;
2015-06-14 03:12:53 +02:00
dock_hb - > add_child ( dock_tab_move_left ) ;
2017-11-19 06:00:42 +01:00
Label * dock_label = memnew ( Label ) ;
dock_label - > set_text ( TTR ( " Dock Position " ) ) ;
dock_label - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2019-12-23 02:37:36 +01:00
dock_label - > set_align ( Label : : ALIGN_CENTER ) ;
2017-11-19 06:00:42 +01:00
dock_hb - > add_child ( dock_label ) ;
2017-03-05 16:44:50 +01:00
dock_tab_move_right = memnew ( ToolButton ) ;
dock_tab_move_right - > set_icon ( theme - > get_icon ( " Forward " , " EditorIcons " ) ) ;
2015-06-14 03:12:53 +02:00
dock_tab_move_right - > set_focus_mode ( Control : : FOCUS_NONE ) ;
2017-03-05 16:44:50 +01:00
dock_tab_move_right - > connect ( " pressed " , this , " _dock_move_right " ) ;
2015-06-14 05:41:08 +02:00
2015-06-14 03:12:53 +02:00
dock_hb - > add_child ( dock_tab_move_right ) ;
dock_vb - > add_child ( dock_hb ) ;
2017-03-05 16:44:50 +01:00
dock_select = memnew ( Control ) ;
2018-10-26 12:44:49 +02:00
dock_select - > set_custom_minimum_size ( Size2 ( 128 , 64 ) * EDSCALE ) ;
2017-03-05 16:44:50 +01:00
dock_select - > connect ( " gui_input " , this , " _dock_select_input " ) ;
dock_select - > connect ( " draw " , this , " _dock_select_draw " ) ;
dock_select - > connect ( " mouse_exited " , this , " _dock_popup_exit " ) ;
2015-06-14 03:12:53 +02:00
dock_select - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
dock_vb - > add_child ( dock_select ) ;
2017-07-18 15:04:20 +02:00
dock_select_popup - > set_as_minsize ( ) ;
2017-03-05 16:44:50 +01:00
dock_select_rect_over = - 1 ;
dock_popup_selected = - 1 ;
for ( int i = 0 ; i < DOCK_SLOT_MAX ; i + + ) {
2018-10-26 12:44:49 +02:00
dock_slot [ i ] - > set_custom_minimum_size ( Size2 ( 170 , 0 ) * EDSCALE ) ;
2015-06-14 03:12:53 +02:00
dock_slot [ i ] - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2017-07-18 15:04:20 +02:00
dock_slot [ i ] - > set_popup ( dock_select_popup ) ;
2017-03-05 16:44:50 +01:00
dock_slot [ i ] - > connect ( " pre_popup_pressed " , this , " _dock_pre_popup " , varray ( i ) ) ;
2017-05-02 22:13:12 +02:00
dock_slot [ i ] - > set_tab_align ( TabContainer : : ALIGN_LEFT ) ;
2018-02-07 14:01:45 +01:00
dock_slot [ i ] - > set_drag_to_rearrange_enabled ( true ) ;
dock_slot [ i ] - > set_tabs_rearrange_group ( 1 ) ;
dock_slot [ i ] - > connect ( " tab_changed " , this , " _dock_tab_changed " ) ;
2019-01-26 19:41:36 +01:00
dock_slot [ i ] - > set_use_hidden_tabs_for_min_size ( true ) ;
2015-06-14 03:12:53 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
dock_drag_timer = memnew ( Timer ) ;
2015-06-14 03:12:53 +02:00
add_child ( dock_drag_timer ) ;
dock_drag_timer - > set_wait_time ( 0.5 ) ;
dock_drag_timer - > set_one_shot ( true ) ;
2017-03-05 16:44:50 +01:00
dock_drag_timer - > connect ( " timeout " , this , " _save_docks " ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
top_split = memnew ( VSplitContainer ) ;
2015-06-14 03:12:53 +02:00
center_split - > add_child ( top_split ) ;
2014-02-10 02:10:30 +01:00
top_split - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
top_split - > set_collapsed ( true ) ;
2017-03-05 16:44:50 +01:00
VBoxContainer * srt = memnew ( VBoxContainer ) ;
2014-02-10 02:10:30 +01:00
srt - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
top_split - > add_child ( srt ) ;
2017-03-05 16:44:50 +01:00
srt - > add_constant_override ( " separation " , 0 ) ;
2014-02-10 02:10:30 +01:00
2017-06-15 17:30:03 +02:00
tab_preview_panel = memnew ( Panel ) ;
tab_preview_panel - > set_size ( Size2 ( 100 , 100 ) * EDSCALE ) ;
tab_preview_panel - > hide ( ) ;
tab_preview_panel - > set_self_modulate ( Color ( 1 , 1 , 1 , 0.7 ) ) ;
gui_base - > add_child ( tab_preview_panel ) ;
tab_preview = memnew ( TextureRect ) ;
tab_preview - > set_stretch_mode ( TextureRect : : STRETCH_KEEP_ASPECT_CENTERED ) ;
tab_preview - > set_size ( Size2 ( 96 , 96 ) * EDSCALE ) ;
tab_preview - > set_position ( Point2 ( 2 , 2 ) * EDSCALE ) ;
tab_preview_panel - > add_child ( tab_preview ) ;
2017-03-05 16:44:50 +01:00
scene_tabs = memnew ( Tabs ) ;
2017-06-15 17:30:03 +02:00
scene_tabs - > add_style_override ( " tab_fg " , gui_base - > get_stylebox ( " SceneTabFG " , " EditorStyles " ) ) ;
scene_tabs - > add_style_override ( " tab_bg " , gui_base - > get_stylebox ( " SceneTabBG " , " EditorStyles " ) ) ;
2018-01-02 08:10:49 +01:00
scene_tabs - > set_select_with_rmb ( true ) ;
2015-11-18 08:47:41 +01:00
scene_tabs - > add_tab ( " unsaved " ) ;
2017-01-23 05:40:43 +01:00
scene_tabs - > set_tab_align ( Tabs : : ALIGN_LEFT ) ;
2017-12-20 19:41:02 +01:00
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 ) ) ;
2017-06-15 17:30:03 +02:00
scene_tabs - > set_min_width ( int ( EDITOR_DEF ( " interface/scene_tabs/minimum_width " , 50 ) ) * EDSCALE ) ;
2018-02-07 14:01:45 +01:00
scene_tabs - > set_drag_to_rearrange_enabled ( true ) ;
2017-03-05 16:44:50 +01:00
scene_tabs - > connect ( " tab_changed " , this , " _scene_tab_changed " ) ;
scene_tabs - > connect ( " right_button_pressed " , this , " _scene_tab_script_edited " ) ;
2019-04-21 11:44:21 +02:00
scene_tabs - > connect ( " tab_close " , this , " _scene_tab_closed " , varray ( SCENE_TAB_CLOSE ) ) ;
2017-06-15 17:30:03 +02:00
scene_tabs - > connect ( " tab_hover " , this , " _scene_tab_hover " ) ;
scene_tabs - > connect ( " mouse_exited " , this , " _scene_tab_exit " ) ;
scene_tabs - > connect ( " gui_input " , this , " _scene_tab_input " ) ;
2017-07-05 15:44:53 +02:00
scene_tabs - > connect ( " reposition_active_tab_request " , this , " _reposition_active_tab " ) ;
2017-11-16 23:57:57 +01:00
scene_tabs - > connect ( " resized " , this , " _update_scene_tabs " ) ;
2015-11-18 08:47:41 +01:00
2017-11-16 23:57:57 +01:00
tabbar_container = memnew ( HBoxContainer ) ;
2017-05-24 12:00:55 +02:00
scene_tabs - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2018-01-02 08:10:49 +01:00
scene_tabs_context_menu = memnew ( PopupMenu ) ;
tabbar_container - > add_child ( scene_tabs_context_menu ) ;
scene_tabs_context_menu - > connect ( " id_pressed " , this , " _menu_option " ) ;
scene_tabs_context_menu - > set_hide_on_window_lose_focus ( true ) ;
2017-05-24 12:00:55 +02:00
srt - > add_child ( tabbar_container ) ;
tabbar_container - > add_child ( scene_tabs ) ;
distraction_free = memnew ( ToolButton ) ;
2018-06-11 07:53:25 +02:00
# ifdef OSX_ENABLED
distraction_free - > set_shortcut ( ED_SHORTCUT ( " editor/distraction_free_mode " , TTR ( " Distraction Free Mode " ) , KEY_MASK_CMD | KEY_MASK_CTRL | KEY_D ) ) ;
# else
2017-05-24 12:00:55 +02:00
distraction_free - > set_shortcut ( ED_SHORTCUT ( " editor/distraction_free_mode " , TTR ( " Distraction Free Mode " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F11 ) ) ;
2018-06-11 07:53:25 +02:00
# endif
2017-07-24 08:07:53 +02:00
distraction_free - > set_tooltip ( TTR ( " Toggle distraction-free mode. " ) ) ;
2017-05-24 12:00:55 +02:00
distraction_free - > connect ( " pressed " , this , " _toggle_distraction_free_mode " ) ;
distraction_free - > set_icon ( gui_base - > get_icon ( " DistractionFree " , " EditorIcons " ) ) ;
distraction_free - > set_toggle_mode ( true ) ;
2014-02-10 02:10:30 +01:00
2017-11-16 23:57:57 +01:00
scene_tab_add = memnew ( ToolButton ) ;
tabbar_container - > add_child ( scene_tab_add ) ;
tabbar_container - > add_child ( distraction_free ) ;
scene_tab_add - > set_tooltip ( TTR ( " Add a new scene. " ) ) ;
scene_tab_add - > set_icon ( gui_base - > get_icon ( " Add " , " EditorIcons " ) ) ;
scene_tab_add - > add_color_override ( " icon_color_normal " , Color ( 0.6f , 0.6f , 0.6f , 0.8f ) ) ;
scene_tab_add - > connect ( " pressed " , this , " _menu_option " , make_binds ( FILE_NEW_SCENE ) ) ;
2017-03-05 16:44:50 +01:00
scene_root_parent = memnew ( PanelContainer ) ;
scene_root_parent - > set_custom_minimum_size ( Size2 ( 0 , 80 ) * EDSCALE ) ;
2017-05-02 22:13:12 +02:00
scene_root_parent - > add_style_override ( " panel " , gui_base - > get_stylebox ( " Content " , " EditorStyles " ) ) ;
2017-09-02 03:29:04 +02:00
scene_root_parent - > set_draw_behind_parent ( true ) ;
2014-02-10 02:10:30 +01:00
srt - > add_child ( scene_root_parent ) ;
scene_root_parent - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2017-03-05 16:44:50 +01:00
scene_root = memnew ( Viewport ) ;
2017-12-19 19:59:32 +01:00
//scene_root->set_usage(Viewport::USAGE_2D); canvas BG mode prevents usage of this as 2D
2016-10-05 06:26:35 +02:00
scene_root - > set_disable_3d ( true ) ;
2017-03-05 16:44:50 +01:00
VisualServer : : get_singleton ( ) - > viewport_set_hide_scenario ( scene_root - > get_viewport_rid ( ) , true ) ;
2016-01-17 02:41:10 +01:00
scene_root - > set_disable_input ( true ) ;
2014-02-10 02:10:30 +01:00
scene_root - > set_as_audio_listener_2d ( true ) ;
2017-03-05 16:44:50 +01:00
viewport = memnew ( VBoxContainer ) ;
2016-02-08 17:01:54 +01:00
viewport - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2017-04-28 04:01:17 +02:00
viewport - > add_constant_override ( " separation " , 0 ) ;
2014-02-10 02:10:30 +01:00
scene_root_parent - > add_child ( viewport ) ;
2017-03-05 16:44:50 +01:00
HBoxContainer * left_menu_hb = memnew ( HBoxContainer ) ;
2019-02-11 05:18:54 +01:00
menu_hb - > add_child ( left_menu_hb ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
file_menu = memnew ( MenuButton ) ;
2017-09-02 03:25:40 +02:00
file_menu - > set_flat ( false ) ;
2018-07-30 00:26:43 +02:00
file_menu - > set_switch_on_hover ( true ) ;
2016-05-04 03:25:37 +02:00
file_menu - > set_text ( TTR ( " Scene " ) ) ;
2017-05-02 22:13:12 +02:00
file_menu - > add_style_override ( " hover " , gui_base - > get_stylebox ( " MenuHover " , " EditorStyles " ) ) ;
2017-09-02 03:25:40 +02:00
left_menu_hb - > add_child ( file_menu ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
prev_scene = memnew ( ToolButton ) ;
prev_scene - > set_icon ( gui_base - > get_icon ( " PrevScene " , " EditorIcons " ) ) ;
2016-05-04 03:25:37 +02:00
prev_scene - > set_tooltip ( TTR ( " Go to previously opened scene. " ) ) ;
2014-02-10 02:10:30 +01:00
prev_scene - > set_disabled ( true ) ;
2017-03-05 16:44:50 +01:00
prev_scene - > connect ( " pressed " , this , " _menu_option " , make_binds ( FILE_OPEN_PREV ) ) ;
2015-04-21 00:38:02 +02:00
gui_base - > add_child ( prev_scene ) ;
2017-03-29 17:29:38 +02:00
prev_scene - > set_position ( Point2 ( 3 , 24 ) ) ;
2015-04-21 00:38:02 +02:00
prev_scene - > hide ( ) ;
2014-02-10 02:10:30 +01:00
2017-08-30 13:59:48 +02:00
accept = memnew ( AcceptDialog ) ;
gui_base - > add_child ( accept ) ;
accept - > connect ( " confirmed " , this , " _menu_confirm_current " ) ;
2021-09-11 03:35:13 +02:00
save_accept = memnew ( AcceptDialog ) ;
gui_base - > add_child ( save_accept ) ;
save_accept - > connect ( " confirmed " , this , " _menu_option " , make_binds ( ( int ) MenuOptions : : FILE_SAVE_AS_SCENE ) ) ;
2017-08-30 13:59:48 +02:00
project_export = memnew ( ProjectExportDialog ) ;
gui_base - > add_child ( project_export ) ;
dependency_error = memnew ( DependencyErrorDialog ) ;
gui_base - > add_child ( dependency_error ) ;
dependency_fixer = memnew ( DependencyEditor ) ;
gui_base - > add_child ( dependency_fixer ) ;
settings_config_dialog = memnew ( EditorSettingsDialog ) ;
gui_base - > add_child ( settings_config_dialog ) ;
project_settings = memnew ( ProjectSettingsEditor ( & editor_data ) ) ;
gui_base - > add_child ( project_settings ) ;
2022-03-28 04:49:13 +02:00
ProjectSettings : : get_singleton ( ) - > connect ( " project_settings_changed " , this , " _project_settings_changed " ) ;
2017-08-30 13:59:48 +02:00
run_settings_dialog = memnew ( RunSettingsDialog ) ;
gui_base - > add_child ( run_settings_dialog ) ;
export_template_manager = memnew ( ExportTemplateManager ) ;
gui_base - > add_child ( export_template_manager ) ;
2019-04-09 00:18:03 +02:00
feature_profile_manager = memnew ( EditorFeatureProfileManager ) ;
gui_base - > add_child ( feature_profile_manager ) ;
2017-08-30 13:59:48 +02:00
about = memnew ( EditorAbout ) ;
gui_base - > add_child ( about ) ;
2019-04-09 00:18:03 +02:00
feature_profile_manager - > connect ( " current_feature_profile_changed " , this , " _feature_profile_changed " ) ;
2017-08-30 13:59:48 +02:00
warning = memnew ( AcceptDialog ) ;
2019-07-09 20:11:31 +02:00
warning - > add_button ( TTR ( " Copy Text " ) , true , " copy " ) ;
2017-08-30 13:59:48 +02:00
gui_base - > add_child ( warning ) ;
2019-07-09 20:11:31 +02:00
warning - > connect ( " custom_action " , this , " _copy_warning " ) ;
2017-08-30 13:59:48 +02:00
2017-03-05 16:44:50 +01:00
ED_SHORTCUT ( " editor/next_tab " , TTR ( " Next tab " ) , KEY_MASK_CMD + KEY_TAB ) ;
ED_SHORTCUT ( " editor/prev_tab " , TTR ( " Previous tab " ) , KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_TAB ) ;
2018-04-22 19:36:01 +02:00
ED_SHORTCUT ( " editor/filter_files " , TTR ( " Filter Files... " ) , KEY_MASK_ALT + KEY_MASK_CMD + KEY_P ) ;
2017-06-22 23:04:03 +02:00
PopupMenu * p ;
2016-06-25 06:42:09 +02:00
2016-05-04 03:25:37 +02:00
file_menu - > set_tooltip ( TTR ( " Operations with scene files. " ) ) ;
2019-04-10 17:21:26 +02:00
2017-03-05 16:44:50 +01:00
p = file_menu - > get_popup ( ) ;
2018-01-02 08:10:49 +01:00
p - > set_hide_on_window_lose_focus ( true ) ;
2022-01-20 20:34:05 +01:00
p - > add_shortcut ( ED_SHORTCUT ( " editor/new_scene " , TTR ( " New Scene " ) , KEY_MASK_CMD + KEY_N ) , FILE_NEW_SCENE ) ;
p - > add_shortcut ( ED_SHORTCUT ( " editor/new_inherited_scene " , TTR ( " New Inherited Scene... " ) , KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_N ) , FILE_NEW_INHERITED_SCENE ) ;
2018-04-22 19:36:01 +02:00
p - > add_shortcut ( ED_SHORTCUT ( " editor/open_scene " , TTR ( " Open Scene... " ) , KEY_MASK_CMD + KEY_O ) , FILE_OPEN_SCENE ) ;
2019-08-12 22:23:00 +02:00
p - > add_shortcut ( ED_SHORTCUT ( " editor/reopen_closed_scene " , TTR ( " Reopen Closed Scene " ) , KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_T ) , FILE_OPEN_PREV ) ;
p - > add_submenu_item ( TTR ( " Open Recent " ) , " RecentScenes " , FILE_OPEN_RECENT ) ;
2015-04-26 04:45:49 +02:00
p - > add_separator ( ) ;
2017-03-05 16:44:50 +01:00
p - > add_shortcut ( ED_SHORTCUT ( " editor/save_scene " , TTR ( " Save Scene " ) , KEY_MASK_CMD + KEY_S ) , FILE_SAVE_SCENE ) ;
2018-04-22 19:36:01 +02:00
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 ) ;
2018-10-26 21:11:36 +02:00
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 ) ;
2019-08-12 22:23:00 +02:00
2014-02-10 02:10:30 +01:00
p - > add_separator ( ) ;
2019-05-09 22:06:35 +02:00
p - > add_shortcut ( ED_SHORTCUT ( " editor/quick_open " , TTR ( " Quick Open... " ) , KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_O ) , FILE_QUICK_OPEN ) ;
2018-04-22 19:36:01 +02:00
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 ) ;
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 ) ;
2019-08-12 22:23:00 +02:00
2014-02-10 02:10:30 +01:00
p - > add_separator ( ) ;
2017-03-05 16:44:50 +01:00
PopupMenu * pm_export = memnew ( PopupMenu ) ;
2014-02-10 02:10:30 +01:00
pm_export - > set_name ( " Export " ) ;
p - > add_child ( pm_export ) ;
2018-04-22 19:36:01 +02:00
p - > add_submenu_item ( TTR ( " Convert To... " ) , " Export " ) ;
pm_export - > add_shortcut ( ED_SHORTCUT ( " editor/convert_to_MeshLibrary " , TTR ( " MeshLibrary... " ) ) , FILE_EXPORT_MESH_LIBRARY ) ;
pm_export - > add_shortcut ( ED_SHORTCUT ( " editor/convert_to_TileSet " , TTR ( " TileSet... " ) ) , FILE_EXPORT_TILESET ) ;
2017-03-05 16:44:50 +01:00
pm_export - > connect ( " id_pressed " , this , " _menu_option " ) ;
2014-02-10 02:10:30 +01:00
p - > add_separator ( ) ;
2017-03-05 16:44:50 +01:00
p - > add_shortcut ( ED_SHORTCUT ( " editor/undo " , TTR ( " Undo " ) , KEY_MASK_CMD + KEY_Z ) , EDIT_UNDO , true ) ;
p - > add_shortcut ( ED_SHORTCUT ( " editor/redo " , TTR ( " Redo " ) , KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_Z ) , EDIT_REDO , true ) ;
2019-08-12 22:23:00 +02:00
2014-02-10 02:10:30 +01:00
p - > add_separator ( ) ;
2020-05-10 20:12:25 +02:00
p - > add_shortcut ( ED_SHORTCUT ( " editor/reload_saved_scene " , TTR ( " Reload Saved Scene " ) ) , EDIT_RELOAD_SAVED_SCENE ) ;
2019-08-12 22:23:00 +02:00
p - > add_shortcut ( ED_SHORTCUT ( " editor/close_scene " , TTR ( " Close Scene " ) , KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_W ) , FILE_CLOSE ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
recent_scenes = memnew ( PopupMenu ) ;
2014-02-10 02:10:30 +01:00
recent_scenes - > set_name ( " RecentScenes " ) ;
p - > add_child ( recent_scenes ) ;
2017-03-05 16:44:50 +01:00
recent_scenes - > connect ( " id_pressed " , this , " _open_recent_scene " ) ;
2014-02-10 02:10:30 +01:00
2017-06-22 23:04:03 +02:00
p - > add_separator ( ) ;
2019-08-05 20:35:54 +02:00
p - > add_shortcut ( ED_SHORTCUT ( " editor/file_quit " , TTR ( " Quit " ) , KEY_MASK_CMD + KEY_Q ) , FILE_QUIT , true ) ;
2017-06-22 23:04:03 +02:00
project_menu = memnew ( MenuButton ) ;
2017-09-02 03:25:40 +02:00
project_menu - > set_flat ( false ) ;
2018-07-30 00:26:43 +02:00
project_menu - > set_switch_on_hover ( true ) ;
2017-06-22 23:04:03 +02:00
project_menu - > set_tooltip ( TTR ( " Miscellaneous project or scene-wide tools. " ) ) ;
project_menu - > set_text ( TTR ( " Project " ) ) ;
project_menu - > add_style_override ( " hover " , gui_base - > get_stylebox ( " MenuHover " , " EditorStyles " ) ) ;
left_menu_hb - > add_child ( project_menu ) ;
p = project_menu - > get_popup ( ) ;
2018-01-02 08:10:49 +01:00
p - > set_hide_on_window_lose_focus ( true ) ;
2019-08-12 22:23:00 +02:00
p - > add_shortcut ( ED_SHORTCUT ( " editor/project_settings " , TTR ( " Project Settings... " ) ) , RUN_SETTINGS ) ;
2017-06-22 23:04:03 +02:00
p - > connect ( " id_pressed " , this , " _menu_option " ) ;
2019-08-12 22:23:00 +02:00
2019-09-03 16:42:08 +02:00
vcs_actions_menu = VersionControlEditorPlugin : : get_singleton ( ) - > get_version_control_actions_panel ( ) ;
vcs_actions_menu - > set_name ( " Version Control " ) ;
vcs_actions_menu - > connect ( " index_pressed " , this , " _version_control_menu_option " ) ;
p - > add_separator ( ) ;
p - > add_child ( vcs_actions_menu ) ;
p - > add_submenu_item ( TTR ( " Version Control " ) , " Version Control " ) ;
vcs_actions_menu - > add_item ( TTR ( " Set Up Version Control " ) , RUN_VCS_SETTINGS ) ;
vcs_actions_menu - > add_item ( TTR ( " Shut Down Version Control " ) , RUN_VCS_SHUT_DOWN ) ;
2019-08-12 22:23:00 +02:00
p - > add_separator ( ) ;
p - > add_shortcut ( ED_SHORTCUT ( " editor/export " , TTR ( " Export... " ) ) , FILE_EXPORT_PROJECT ) ;
2022-07-13 19:39:08 +02:00
# ifndef ANDROID_ENABLED
2019-08-12 22:23:00 +02:00
p - > add_item ( TTR ( " Install Android Build Template... " ) , FILE_INSTALL_ANDROID_SOURCE ) ;
2021-12-28 01:51:45 +01:00
p - > add_item ( TTR ( " Open User Data Folder " ) , RUN_USER_DATA_FOLDER ) ;
2022-07-13 19:39:08 +02:00
# endif
2017-06-22 23:04:03 +02:00
2018-07-19 17:34:22 +02:00
plugin_config_dialog = memnew ( PluginConfigDialog ) ;
plugin_config_dialog - > connect ( " plugin_ready " , this , " _on_plugin_ready " ) ;
gui_base - > add_child ( plugin_config_dialog ) ;
2018-03-17 02:50:35 +01:00
tool_menu = memnew ( PopupMenu ) ;
2017-06-22 23:04:03 +02:00
tool_menu - > set_name ( " Tools " ) ;
2018-03-17 02:50:35 +01:00
tool_menu - > connect ( " index_pressed " , this , " _tool_menu_option " ) ;
2017-06-22 23:04:03 +02:00
p - > add_child ( tool_menu ) ;
p - > add_submenu_item ( TTR ( " Tools " ) , " Tools " ) ;
2019-08-12 22:23:00 +02:00
tool_menu - > add_item ( TTR ( " Orphan Resource Explorer... " ) , TOOLS_ORPHAN_RESOURCES ) ;
2018-07-25 19:53:12 +02:00
2019-08-12 22:23:00 +02:00
p - > add_separator ( ) ;
2022-03-23 12:07:29 +01:00
p - > add_shortcut ( ED_SHORTCUT ( " editor/reload_current_project " , TTR ( " Reload Current Project " ) ) , RELOAD_CURRENT_PROJECT ) ;
2017-06-22 23:04:03 +02:00
# ifdef OSX_ENABLED
2019-08-05 20:35:54 +02:00
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 ) ;
2017-06-22 23:04:03 +02:00
# else
2019-08-05 20:35:54 +02:00
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 ) ;
2017-06-22 23:04:03 +02:00
# endif
2015-11-18 08:47:41 +01:00
2017-05-24 12:00:55 +02:00
menu_hb - > add_spacer ( ) ;
2019-02-11 05:18:54 +01:00
main_editor_button_vb = memnew ( HBoxContainer ) ;
menu_hb - > add_child ( main_editor_button_vb ) ;
2016-09-13 14:46:17 +02:00
2017-05-24 12:00:55 +02:00
debug_menu = memnew ( MenuButton ) ;
2017-09-02 03:25:40 +02:00
debug_menu - > set_flat ( false ) ;
2018-07-30 00:26:43 +02:00
debug_menu - > set_switch_on_hover ( true ) ;
2017-05-24 12:00:55 +02:00
debug_menu - > set_text ( TTR ( " Debug " ) ) ;
debug_menu - > add_style_override ( " hover " , gui_base - > get_stylebox ( " MenuHover " , " EditorStyles " ) ) ;
left_menu_hb - > add_child ( debug_menu ) ;
2017-09-02 03:25:40 +02:00
2017-05-24 12:00:55 +02:00
p = debug_menu - > get_popup ( ) ;
2018-01-02 08:10:49 +01:00
p - > set_hide_on_window_lose_focus ( true ) ;
2019-11-25 16:25:54 +01:00
p - > set_hide_on_checkable_item_selection ( false ) ;
2021-09-26 21:31:17 +02:00
2019-03-03 22:24:58 +01:00
p - > add_check_shortcut ( ED_SHORTCUT ( " editor/deploy_with_remote_debug " , TTR ( " Deploy with Remote Debug " ) ) , RUN_DEPLOY_REMOTE_DEBUG ) ;
2020-08-03 14:14:59 +02:00
p - > set_item_tooltip (
p - > get_item_count ( ) - 1 ,
TTR ( " When this option is enabled, using one-click deploy will make the executable attempt to connect to this computer's IP so the running project can be debugged. \n This option is intended to be used for remote debugging (typically with a mobile device). \n You don't need to enable it to use the GDScript debugger locally. " ) ) ;
2021-09-26 21:31:17 +02:00
2020-08-03 14:14:59 +02:00
p - > add_check_shortcut ( ED_SHORTCUT ( " editor/small_deploy_with_network_fs " , TTR ( " Small Deploy with Network Filesystem " ) ) , RUN_FILE_SERVER ) ;
p - > set_item_tooltip (
p - > get_item_count ( ) - 1 ,
TTR ( " When this option is enabled, using one-click deploy for Android will only export an executable without the project data. \n The filesystem will be provided from the project by the editor over the network. \n On Android, deploying will use the USB cable for faster performance. This option speeds up testing for projects with large assets. " ) ) ;
2021-09-26 21:31:17 +02:00
2017-05-24 12:00:55 +02:00
p - > add_separator ( ) ;
2021-09-26 21:31:17 +02:00
2019-03-03 22:24:58 +01:00
p - > add_check_shortcut ( ED_SHORTCUT ( " editor/visible_collision_shapes " , TTR ( " Visible Collision Shapes " ) ) , RUN_DEBUG_COLLISONS ) ;
2020-08-03 14:14:59 +02:00
p - > set_item_tooltip (
p - > get_item_count ( ) - 1 ,
TTR ( " When this option is enabled, collision shapes and raycast nodes (for 2D and 3D) will be visible in the running project. " ) ) ;
2021-09-26 21:31:17 +02:00
2019-03-03 22:24:58 +01:00
p - > add_check_shortcut ( ED_SHORTCUT ( " editor/visible_navigation " , TTR ( " Visible Navigation " ) ) , RUN_DEBUG_NAVIGATION ) ;
2020-08-03 14:14:59 +02:00
p - > set_item_tooltip (
p - > get_item_count ( ) - 1 ,
TTR ( " When this option is enabled, navigation meshes and polygons will be visible in the running project. " ) ) ;
2021-09-26 21:31:17 +02:00
if ( GLOBAL_GET ( " rendering/quality/driver/driver_name " ) = = " GLES3 " ) {
p - > add_separator ( ) ;
p - > add_check_shortcut ( ED_SHORTCUT ( " editor/use_shader_fallbacks " , TTR ( " Force Shader Fallbacks " ) ) , RUN_DEBUG_SHADER_FALLBACKS ) ;
p - > set_item_tooltip (
p - > get_item_count ( ) - 1 ,
TTR ( " When this option is enabled, shaders will be used in their fallback form (either visible via an ubershader or hidden) during all the run time. \n This is useful for verifying the look and performance of fallbacks, which are normally displayed briefly. \n Asynchronous shader compilation must be enabled in the project settings for this option to make a difference. " ) ) ;
}
2017-05-24 12:00:55 +02:00
p - > add_separator ( ) ;
2021-09-26 21:31:17 +02:00
2020-08-03 14:14:59 +02:00
p - > add_check_shortcut ( ED_SHORTCUT ( " editor/sync_scene_changes " , TTR ( " Synchronize Scene Changes " ) ) , RUN_LIVE_DEBUG ) ;
p - > set_item_tooltip (
p - > get_item_count ( ) - 1 ,
TTR ( " When this option is enabled, any changes made to the scene in the editor will be replicated in the running project. \n When used remotely on a device, this is more efficient when the network filesystem option is enabled. " ) ) ;
2021-09-26 21:31:17 +02:00
2020-08-03 14:14:59 +02:00
p - > add_check_shortcut ( ED_SHORTCUT ( " editor/sync_script_changes " , TTR ( " Synchronize Script Changes " ) ) , RUN_RELOAD_SCRIPTS ) ;
p - > set_item_tooltip (
p - > get_item_count ( ) - 1 ,
TTR ( " When this option is enabled, any script that is saved will be reloaded in the running project. \n When used remotely on a device, this is more efficient when the network filesystem option is enabled. " ) ) ;
2021-09-26 21:31:17 +02:00
2017-05-24 12:00:55 +02:00
p - > connect ( " id_pressed " , this , " _menu_option " ) ;
2015-11-29 05:08:31 +01:00
2017-05-24 12:00:55 +02:00
menu_hb - > add_spacer ( ) ;
2015-11-29 05:08:31 +01:00
2017-05-24 12:00:55 +02:00
settings_menu = memnew ( MenuButton ) ;
2017-09-02 03:25:40 +02:00
settings_menu - > set_flat ( false ) ;
2018-07-30 00:26:43 +02:00
settings_menu - > set_switch_on_hover ( true ) ;
2017-05-24 12:00:55 +02:00
settings_menu - > set_text ( TTR ( " Editor " ) ) ;
settings_menu - > add_style_override ( " hover " , gui_base - > get_stylebox ( " MenuHover " , " EditorStyles " ) ) ;
2017-09-02 03:25:40 +02:00
left_menu_hb - > add_child ( settings_menu ) ;
2015-11-29 05:08:31 +01:00
2018-01-02 08:10:49 +01:00
p = settings_menu - > get_popup ( ) ;
p - > set_hide_on_window_lose_focus ( true ) ;
2020-05-04 12:30:57 +02:00
# ifdef OSX_ENABLED
p - > add_shortcut ( ED_SHORTCUT ( " editor/editor_settings " , TTR ( " Editor Settings... " ) , KEY_MASK_CMD + KEY_COMMA ) , SETTINGS_PREFERENCES ) ;
# else
2019-08-12 22:23:00 +02:00
p - > add_shortcut ( ED_SHORTCUT ( " editor/editor_settings " , TTR ( " Editor Settings... " ) ) , SETTINGS_PREFERENCES ) ;
2020-05-04 12:30:57 +02:00
# endif
2017-05-24 12:00:55 +02:00
p - > add_separator ( ) ;
2018-07-25 19:53:12 +02:00
2017-05-24 12:00:55 +02:00
editor_layouts = memnew ( PopupMenu ) ;
editor_layouts - > set_name ( " Layouts " ) ;
p - > add_child ( editor_layouts ) ;
editor_layouts - > connect ( " id_pressed " , this , " _layout_menu_option " ) ;
p - > add_submenu_item ( TTR ( " Editor Layout " ) , " Layouts " ) ;
2019-07-23 07:05:29 +02:00
p - > add_separator ( ) ;
2019-03-29 14:53:11 +01:00
# ifdef OSX_ENABLED
p - > add_shortcut ( ED_SHORTCUT ( " editor/take_screenshot " , TTR ( " Take Screenshot " ) , KEY_MASK_CMD | KEY_F12 ) , EDITOR_SCREENSHOT ) ;
# else
p - > add_shortcut ( ED_SHORTCUT ( " editor/take_screenshot " , TTR ( " Take Screenshot " ) , KEY_MASK_CTRL | KEY_F12 ) , EDITOR_SCREENSHOT ) ;
# endif
p - > set_item_tooltip ( p - > get_item_count ( ) - 1 , TTR ( " Screenshots are stored in the Editor Data/Settings Folder. " ) ) ;
2022-07-13 19:39:08 +02:00
# ifndef ANDROID_ENABLED
2018-06-11 07:53:25 +02:00
# ifdef OSX_ENABLED
p - > add_shortcut ( ED_SHORTCUT ( " editor/fullscreen_mode " , TTR ( " Toggle Fullscreen " ) , KEY_MASK_CMD | KEY_MASK_CTRL | KEY_F ) , SETTINGS_TOGGLE_FULLSCREEN ) ;
# else
p - > add_shortcut ( ED_SHORTCUT ( " editor/fullscreen_mode " , TTR ( " Toggle Fullscreen " ) , KEY_MASK_SHIFT | KEY_F11 ) , SETTINGS_TOGGLE_FULLSCREEN ) ;
2022-07-13 19:39:08 +02:00
# endif
2018-06-11 07:53:25 +02:00
# endif
2017-05-24 12:00:55 +02:00
p - > add_separator ( ) ;
2018-07-25 19:53:12 +02:00
2022-07-13 19:39:08 +02:00
# ifndef ANDROID_ENABLED
2018-07-25 19:53:12 +02:00
if ( OS : : get_singleton ( ) - > get_data_path ( ) = = OS : : get_singleton ( ) - > get_config_path ( ) ) {
// Configuration and data folders are located in the same place (Windows/macOS)
p - > add_item ( TTR ( " Open Editor Data/Settings Folder " ) , SETTINGS_EDITOR_DATA_FOLDER ) ;
} else {
// Separate configuration and data folders (Linux)
p - > add_item ( TTR ( " Open Editor Data Folder " ) , SETTINGS_EDITOR_DATA_FOLDER ) ;
p - > add_item ( TTR ( " Open Editor Settings Folder " ) , SETTINGS_EDITOR_CONFIG_FOLDER ) ;
}
p - > add_separator ( ) ;
2022-07-13 19:39:08 +02:00
# endif
2018-07-25 19:53:12 +02:00
2019-08-12 22:23:00 +02:00
p - > add_item ( TTR ( " Manage Editor Features... " ) , SETTINGS_MANAGE_FEATURE_PROFILES ) ;
2022-07-13 19:39:08 +02:00
# ifndef ANDROID_ENABLED
2019-08-12 22:23:00 +02:00
p - > add_item ( TTR ( " Manage Export Templates... " ) , SETTINGS_MANAGE_EXPORT_TEMPLATES ) ;
2022-07-13 19:39:08 +02:00
# endif
2017-05-26 16:34:41 +02:00
// Help Menu
2017-09-02 03:25:40 +02:00
help_menu = memnew ( MenuButton ) ;
help_menu - > set_flat ( false ) ;
2018-07-30 00:26:43 +02:00
help_menu - > set_switch_on_hover ( true ) ;
2017-05-26 16:34:41 +02:00
help_menu - > set_text ( TTR ( " Help " ) ) ;
help_menu - > add_style_override ( " hover " , gui_base - > get_stylebox ( " MenuHover " , " EditorStyles " ) ) ;
2017-09-02 03:25:40 +02:00
left_menu_hb - > add_child ( help_menu ) ;
2017-05-26 16:34:41 +02:00
p = help_menu - > get_popup ( ) ;
2018-01-02 08:10:49 +01:00
p - > set_hide_on_window_lose_focus ( true ) ;
2017-05-26 16:34:41 +02:00
p - > connect ( " id_pressed " , this , " _menu_option " ) ;
2021-02-20 22:15:26 +01:00
# ifdef OSX_ENABLED
p - > add_icon_shortcut ( gui_base - > get_icon ( " HelpSearch " , " EditorIcons " ) , ED_SHORTCUT ( " editor/editor_help " , TTR ( " Search Help " ) , KEY_MASK_ALT | KEY_SPACE ) , HELP_SEARCH ) ;
# else
p - > add_icon_shortcut ( gui_base - > get_icon ( " HelpSearch " , " EditorIcons " ) , ED_SHORTCUT ( " editor/editor_help " , TTR ( " Search Help " ) , KEY_F1 ) , HELP_SEARCH ) ;
# endif
2017-05-26 16:34:41 +02:00
p - > add_separator ( ) ;
2022-04-24 17:21:14 +02:00
p - > add_icon_shortcut ( gui_base - > get_icon ( " ExternalLink " , " EditorIcons " ) , ED_SHORTCUT ( " editor/online_docs " , TTR ( " Online Documentation " ) ) , HELP_DOCS ) ;
p - > add_icon_shortcut ( gui_base - > get_icon ( " ExternalLink " , " EditorIcons " ) , ED_SHORTCUT ( " editor/q&a " , TTR ( " Questions & Answers " ) ) , HELP_QA ) ;
p - > add_icon_shortcut ( gui_base - > get_icon ( " ExternalLink " , " EditorIcons " ) , ED_SHORTCUT ( " editor/report_a_bug " , TTR ( " Report a Bug " ) ) , HELP_REPORT_A_BUG ) ;
p - > add_icon_shortcut ( gui_base - > get_icon ( " ExternalLink " , " EditorIcons " ) , ED_SHORTCUT ( " editor/suggest_a_feature " , TTR ( " Suggest a Feature " ) ) , HELP_SUGGEST_A_FEATURE ) ;
p - > add_icon_shortcut ( gui_base - > get_icon ( " ExternalLink " , " EditorIcons " ) , ED_SHORTCUT ( " editor/send_docs_feedback " , TTR ( " Send Docs Feedback " ) ) , HELP_SEND_DOCS_FEEDBACK ) ;
p - > add_icon_shortcut ( gui_base - > get_icon ( " ExternalLink " , " EditorIcons " ) , ED_SHORTCUT ( " editor/community " , TTR ( " Community " ) ) , HELP_COMMUNITY ) ;
2017-05-24 12:00:55 +02:00
p - > add_separator ( ) ;
2021-05-15 01:57:21 +02:00
p - > add_icon_shortcut ( gui_base - > get_icon ( " Godot " , " EditorIcons " ) , ED_SHORTCUT ( " editor/about " , TTR ( " About Godot " ) ) , HELP_ABOUT ) ;
p - > add_icon_shortcut ( gui_base - > get_icon ( " Heart " , " EditorIcons " ) , ED_SHORTCUT ( " editor/support_development " , TTR ( " Support Godot Development " ) ) , HELP_SUPPORT_GODOT_DEVELOPMENT ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
HBoxContainer * play_hb = memnew ( HBoxContainer ) ;
2019-02-11 05:18:54 +01:00
menu_hb - > add_child ( play_hb ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
play_button = memnew ( ToolButton ) ;
2014-02-10 02:10:30 +01:00
play_hb - > add_child ( play_button ) ;
play_button - > set_toggle_mode ( true ) ;
2017-03-05 16:44:50 +01:00
play_button - > set_icon ( gui_base - > get_icon ( " MainPlay " , " EditorIcons " ) ) ;
2014-02-10 02:10:30 +01:00
play_button - > set_focus_mode ( Control : : FOCUS_NONE ) ;
2017-03-05 16:44:50 +01:00
play_button - > connect ( " pressed " , this , " _menu_option " , make_binds ( RUN_PLAY ) ) ;
2016-06-05 02:31:29 +02:00
play_button - > set_tooltip ( TTR ( " Play the project. " ) ) ;
2018-06-11 07:53:25 +02:00
# ifdef OSX_ENABLED
play_button - > set_shortcut ( ED_SHORTCUT ( " editor/play " , TTR ( " Play " ) , KEY_MASK_CMD | KEY_B ) ) ;
# else
2017-03-05 16:44:50 +01:00
play_button - > set_shortcut ( ED_SHORTCUT ( " editor/play " , TTR ( " Play " ) , KEY_F5 ) ) ;
2018-06-11 07:53:25 +02:00
# endif
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
pause_button = memnew ( ToolButton ) ;
2014-02-10 02:10:30 +01:00
pause_button - > set_toggle_mode ( true ) ;
2017-03-05 16:44:50 +01:00
pause_button - > set_icon ( gui_base - > get_icon ( " Pause " , " EditorIcons " ) ) ;
2014-02-10 02:10:30 +01:00
pause_button - > set_focus_mode ( Control : : FOCUS_NONE ) ;
2019-11-14 11:44:03 +01:00
pause_button - > set_tooltip ( TTR ( " Pause the scene execution for debugging. " ) ) ;
2016-05-22 02:18:16 +02:00
pause_button - > set_disabled ( true ) ;
play_hb - > add_child ( pause_button ) ;
2018-06-11 07:53:25 +02:00
# ifdef OSX_ENABLED
pause_button - > set_shortcut ( ED_SHORTCUT ( " editor/pause_scene " , TTR ( " Pause Scene " ) , KEY_MASK_CMD | KEY_MASK_CTRL | KEY_Y ) ) ;
# else
2017-03-05 16:44:50 +01:00
pause_button - > set_shortcut ( ED_SHORTCUT ( " editor/pause_scene " , TTR ( " Pause Scene " ) , KEY_F7 ) ) ;
2018-06-11 07:53:25 +02:00
# endif
2016-05-22 03:34:55 +02:00
2017-03-05 16:44:50 +01:00
stop_button = memnew ( ToolButton ) ;
2014-02-10 02:10:30 +01:00
play_hb - > add_child ( stop_button ) ;
stop_button - > set_focus_mode ( Control : : FOCUS_NONE ) ;
2017-08-19 09:09:58 +02:00
stop_button - > set_icon ( gui_base - > get_icon ( " Stop " , " EditorIcons " ) ) ;
2017-03-05 16:44:50 +01:00
stop_button - > connect ( " pressed " , this , " _menu_option " , make_binds ( RUN_STOP ) ) ;
2016-06-05 02:31:29 +02:00
stop_button - > set_tooltip ( TTR ( " Stop the scene. " ) ) ;
2017-12-04 20:48:46 +01:00
stop_button - > set_disabled ( true ) ;
2018-06-11 07:53:25 +02:00
# ifdef OSX_ENABLED
stop_button - > set_shortcut ( ED_SHORTCUT ( " editor/stop " , TTR ( " Stop " ) , KEY_MASK_CMD | KEY_PERIOD ) ) ;
# else
2017-03-05 16:44:50 +01:00
stop_button - > set_shortcut ( ED_SHORTCUT ( " editor/stop " , TTR ( " Stop " ) , KEY_F8 ) ) ;
2018-06-11 07:53:25 +02:00
# endif
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
run_native = memnew ( EditorRunNative ) ;
2014-02-10 02:10:30 +01:00
play_hb - > add_child ( run_native ) ;
2017-03-05 16:44:50 +01:00
run_native - > connect ( " native_run " , this , " _menu_option " , varray ( RUN_PLAY_NATIVE ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
play_scene_button = memnew ( ToolButton ) ;
2014-02-10 02:10:30 +01:00
play_hb - > add_child ( play_scene_button ) ;
play_scene_button - > set_toggle_mode ( true ) ;
play_scene_button - > set_focus_mode ( Control : : FOCUS_NONE ) ;
2017-03-05 16:44:50 +01:00
play_scene_button - > set_icon ( gui_base - > get_icon ( " PlayScene " , " EditorIcons " ) ) ;
play_scene_button - > connect ( " pressed " , this , " _menu_option " , make_binds ( RUN_PLAY_SCENE ) ) ;
2016-06-05 02:31:29 +02:00
play_scene_button - > set_tooltip ( TTR ( " Play the edited scene. " ) ) ;
2018-06-11 07:53:25 +02:00
# ifdef OSX_ENABLED
play_scene_button - > set_shortcut ( ED_SHORTCUT ( " editor/play_scene " , TTR ( " Play Scene " ) , KEY_MASK_CMD | KEY_R ) ) ;
# else
2017-03-05 16:44:50 +01:00
play_scene_button - > set_shortcut ( ED_SHORTCUT ( " editor/play_scene " , TTR ( " Play Scene " ) , KEY_F6 ) ) ;
2018-06-11 07:53:25 +02:00
# endif
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
play_custom_scene_button = memnew ( ToolButton ) ;
2014-02-10 02:10:30 +01:00
play_hb - > add_child ( play_custom_scene_button ) ;
play_custom_scene_button - > set_toggle_mode ( true ) ;
play_custom_scene_button - > set_focus_mode ( Control : : FOCUS_NONE ) ;
2017-03-05 16:44:50 +01:00
play_custom_scene_button - > set_icon ( gui_base - > get_icon ( " PlayCustom " , " EditorIcons " ) ) ;
play_custom_scene_button - > connect ( " pressed " , this , " _menu_option " , make_binds ( RUN_PLAY_CUSTOM_SCENE ) ) ;
2016-07-11 19:46:41 +02:00
play_custom_scene_button - > set_tooltip ( TTR ( " Play custom scene " ) ) ;
2018-06-11 07:53:25 +02:00
# ifdef OSX_ENABLED
play_custom_scene_button - > set_shortcut ( ED_SHORTCUT ( " editor/play_custom_scene " , TTR ( " Play Custom Scene " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R ) ) ;
# else
2017-03-05 16:44:50 +01:00
play_custom_scene_button - > set_shortcut ( ED_SHORTCUT ( " editor/play_custom_scene " , TTR ( " Play Custom Scene " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F5 ) ) ;
2018-06-11 07:53:25 +02:00
# endif
2014-02-10 02:10:30 +01:00
2018-12-09 19:10:07 +01:00
HBoxContainer * right_menu_hb = memnew ( HBoxContainer ) ;
menu_hb - > add_child ( right_menu_hb ) ;
2018-09-13 12:14:58 +02:00
// Toggle for video driver
2018-07-19 23:58:15 +02:00
video_driver = memnew ( OptionButton ) ;
video_driver - > set_flat ( true ) ;
video_driver - > set_focus_mode ( Control : : FOCUS_NONE ) ;
2018-09-13 12:14:58 +02:00
video_driver - > connect ( " item_selected " , this , " _video_driver_selected " ) ;
2018-09-28 21:40:20 +02:00
video_driver - > add_font_override ( " font " , gui_base - > get_font ( " bold " , " EditorFonts " ) ) ;
2018-12-09 19:10:07 +01:00
right_menu_hb - > add_child ( video_driver ) ;
2018-09-13 12:14:58 +02:00
2018-07-19 23:58:15 +02:00
String video_drivers = ProjectSettings : : get_singleton ( ) - > get_custom_property_info ( ) [ " rendering/quality/driver/driver_name " ] . hint_string ;
String current_video_driver = OS : : get_singleton ( ) - > get_video_driver_name ( OS : : get_singleton ( ) - > get_current_video_driver ( ) ) ;
video_driver_current = 0 ;
for ( int i = 0 ; i < video_drivers . get_slice_count ( " , " ) ; i + + ) {
String driver = video_drivers . get_slice ( " , " , i ) ;
2018-09-13 12:14:58 +02:00
video_driver - > add_item ( driver ) ;
2018-07-19 23:58:15 +02:00
video_driver - > set_item_metadata ( i , driver ) ;
if ( current_video_driver = = driver ) {
video_driver - > select ( i ) ;
video_driver_current = i ;
}
}
2018-09-28 21:40:20 +02:00
_update_video_driver_color ( ) ;
2018-07-19 23:58:15 +02:00
video_restart_dialog = memnew ( ConfirmationDialog ) ;
video_restart_dialog - > set_text ( TTR ( " Changing the video driver requires restarting the editor. " ) ) ;
video_restart_dialog - > get_ok ( ) - > set_text ( TTR ( " Save & Restart " ) ) ;
video_restart_dialog - > connect ( " confirmed " , this , " _menu_option " , varray ( SET_VIDEO_DRIVER_SAVE_AND_RESTART ) ) ;
2018-07-20 23:14:33 +02:00
gui_base - > add_child ( video_restart_dialog ) ;
2018-07-19 23:58:15 +02:00
2017-03-05 16:44:50 +01:00
progress_hb = memnew ( BackgroundProgress ) ;
2015-11-18 08:47:41 +01:00
2019-05-30 20:16:40 +02:00
layout_dialog = memnew ( EditorLayoutsDialog ) ;
2015-11-22 19:11:17 +01:00
gui_base - > add_child ( layout_dialog ) ;
layout_dialog - > set_hide_on_ok ( false ) ;
2019-05-30 20:16:40 +02:00
layout_dialog - > set_size ( Size2 ( 225 , 270 ) * EDSCALE ) ;
2017-03-05 16:44:50 +01:00
layout_dialog - > connect ( " name_confirmed " , this , " _dialog_action " ) ;
2014-02-10 02:10:30 +01:00
2018-12-11 16:52:25 +01:00
update_spinner = memnew ( MenuButton ) ;
right_menu_hb - > add_child ( update_spinner ) ;
update_spinner - > set_icon ( gui_base - > get_icon ( " Progress1 " , " EditorIcons " ) ) ;
update_spinner - > get_popup ( ) - > connect ( " id_pressed " , this , " _menu_option " ) ;
p = update_spinner - > get_popup ( ) ;
p - > add_radio_check_item ( TTR ( " Update Continuously " ) , SETTINGS_UPDATE_CONTINUOUSLY ) ;
2021-10-05 20:05:57 +02:00
p - > add_radio_check_item ( TTR ( " Update All Changes " ) , SETTINGS_UPDATE_WHEN_CHANGED ) ;
p - > add_radio_check_item ( TTR ( " Update Vital Changes " ) , SETTINGS_UPDATE_VITAL_ONLY ) ;
2017-03-05 16:44:50 +01:00
p - > add_separator ( ) ;
2018-12-11 16:52:25 +01:00
p - > add_item ( TTR ( " Hide Update Spinner " ) , SETTINGS_UPDATE_SPINNER_HIDE ) ;
_update_update_spinner ( ) ;
2015-11-18 08:47:41 +01:00
2018-09-14 16:56:18 +02:00
// Instantiate and place editor docks
2014-02-10 02:10:30 +01:00
2018-09-14 16:56:18 +02:00
scene_tree_dock = memnew ( SceneTreeDock ( this , scene_root , editor_selection , editor_data ) ) ;
2018-05-17 08:01:47 +02:00
inspector_dock = memnew ( InspectorDock ( this , editor_data ) ) ;
2018-09-14 16:56:18 +02:00
import_dock = memnew ( ImportDock ) ;
node_dock = memnew ( NodeDock ) ;
2015-09-01 05:49:47 +02:00
2018-09-14 16:56:18 +02:00
filesystem_dock = memnew ( FileSystemDock ( this ) ) ;
2019-05-08 04:35:23 +02:00
filesystem_dock - > connect ( " inherit " , this , " _inherit_request " ) ;
2018-09-14 16:56:18 +02:00
filesystem_dock - > connect ( " instance " , this , " _instance_request " ) ;
2019-02-25 23:39:49 +01:00
filesystem_dock - > connect ( " display_mode_changed " , this , " _save_docks " ) ;
2015-09-01 05:49:47 +02:00
2018-09-14 17:07:46 +02:00
// Scene: Top left
dock_slot [ DOCK_SLOT_LEFT_UR ] - > add_child ( scene_tree_dock ) ;
dock_slot [ DOCK_SLOT_LEFT_UR ] - > set_tab_title ( scene_tree_dock - > get_index ( ) , TTR ( " Scene " ) ) ;
2018-09-14 16:56:18 +02:00
2018-09-14 17:07:46 +02:00
// Import: Top left, behind Scene
dock_slot [ DOCK_SLOT_LEFT_UR ] - > add_child ( import_dock ) ;
dock_slot [ DOCK_SLOT_LEFT_UR ] - > set_tab_title ( import_dock - > get_index ( ) , TTR ( " Import " ) ) ;
2018-09-14 16:56:18 +02:00
2018-09-14 17:07:46 +02:00
// FileSystem: Bottom left
dock_slot [ DOCK_SLOT_LEFT_BR ] - > add_child ( filesystem_dock ) ;
dock_slot [ DOCK_SLOT_LEFT_BR ] - > set_tab_title ( filesystem_dock - > get_index ( ) , TTR ( " FileSystem " ) ) ;
2017-02-01 13:45:45 +01:00
2018-09-14 17:07:46 +02:00
// Inspector: Full height right
dock_slot [ DOCK_SLOT_RIGHT_UL ] - > add_child ( inspector_dock ) ;
dock_slot [ DOCK_SLOT_RIGHT_UL ] - > set_tab_title ( inspector_dock - > get_index ( ) , TTR ( " Inspector " ) ) ;
2017-03-24 17:39:16 +01:00
2018-09-14 17:07:46 +02:00
// Node: Full height right, behind Inspector
dock_slot [ DOCK_SLOT_RIGHT_UL ] - > add_child ( node_dock ) ;
dock_slot [ DOCK_SLOT_RIGHT_UL ] - > set_tab_title ( node_dock - > get_index ( ) , TTR ( " Node " ) ) ;
2016-06-04 02:03:09 +02:00
2018-09-14 16:56:18 +02:00
// Hide unused dock slots and vsplits
dock_slot [ DOCK_SLOT_LEFT_UL ] - > hide ( ) ;
dock_slot [ DOCK_SLOT_LEFT_BL ] - > hide ( ) ;
2018-09-14 17:07:46 +02:00
dock_slot [ DOCK_SLOT_RIGHT_BL ] - > hide ( ) ;
2018-09-14 16:56:18 +02:00
dock_slot [ DOCK_SLOT_RIGHT_UR ] - > hide ( ) ;
dock_slot [ DOCK_SLOT_RIGHT_BR ] - > hide ( ) ;
left_l_vsplit - > hide ( ) ;
right_r_vsplit - > hide ( ) ;
2016-09-13 16:20:09 +02:00
2018-09-14 17:07:46 +02:00
// Add some offsets to left_r and main hsplits to make LEFT_R and RIGHT_L docks wider than minsize
2018-10-26 12:44:49 +02:00
left_r_hsplit - > set_split_offset ( 70 * EDSCALE ) ;
main_hsplit - > set_split_offset ( - 70 * EDSCALE ) ;
2018-09-14 17:07:46 +02:00
2018-09-14 16:56:18 +02:00
// Define corresponding default layout
2014-02-10 02:10:30 +01:00
2015-11-22 19:11:17 +01:00
const String docks_section = " docks " ;
2017-03-05 16:44:50 +01:00
overridden_default_layout = - 1 ;
2016-01-11 22:23:45 +01:00
default_layout . instance ( ) ;
2018-09-14 16:56:18 +02:00
// Dock numbers are based on DockSlot enum value + 1
2018-09-14 17:07:46 +02:00
default_layout - > set_value ( docks_section , " dock_3 " , " Scene,Import " ) ;
default_layout - > set_value ( docks_section , " dock_4 " , " FileSystem " ) ;
default_layout - > set_value ( docks_section , " dock_5 " , " Inspector,Node " ) ;
2015-11-22 19:11:17 +01:00
2021-05-05 12:44:11 +02:00
for ( int i = 0 ; i < vsplits . size ( ) ; i + + ) {
2017-03-05 16:44:50 +01:00
default_layout - > set_value ( docks_section , " dock_split_ " + itos ( i + 1 ) , 0 ) ;
2021-05-05 12:44:11 +02:00
}
2018-09-14 17:07:46 +02:00
default_layout - > set_value ( docks_section , " dock_hsplit_1 " , 0 ) ;
2018-10-26 12:44:49 +02:00
default_layout - > set_value ( docks_section , " dock_hsplit_2 " , 70 * EDSCALE ) ;
default_layout - > set_value ( docks_section , " dock_hsplit_3 " , - 70 * EDSCALE ) ;
2018-09-14 17:07:46 +02:00
default_layout - > set_value ( docks_section , " dock_hsplit_4 " , 0 ) ;
2014-02-10 02:10:30 +01:00
2015-11-22 19:11:17 +01:00
_update_layouts_menu ( ) ;
2014-02-10 02:10:30 +01:00
2018-09-14 16:56:18 +02:00
// Bottom panels
2017-03-05 16:44:50 +01:00
bottom_panel = memnew ( PanelContainer ) ;
2017-07-15 06:40:17 +02:00
bottom_panel - > add_style_override ( " panel " , gui_base - > get_stylebox ( " panel " , " TabContainer " ) ) ;
2016-01-18 00:03:57 +01:00
center_split - > add_child ( bottom_panel ) ;
center_split - > set_dragger_visibility ( SplitContainer : : DRAGGER_HIDDEN ) ;
2015-11-18 08:47:41 +01:00
2017-03-05 16:44:50 +01:00
bottom_panel_vb = memnew ( VBoxContainer ) ;
2016-01-18 00:03:57 +01:00
bottom_panel - > add_child ( bottom_panel_vb ) ;
2015-11-18 08:47:41 +01:00
2017-03-05 16:44:50 +01:00
bottom_panel_hb = memnew ( HBoxContainer ) ;
2019-01-26 22:07:32 +01:00
bottom_panel_hb - > set_custom_minimum_size ( Size2 ( 0 , 24 * EDSCALE ) ) ; // Adjust for the height of the "Expand Bottom Dock" icon.
2016-01-18 00:03:57 +01:00
bottom_panel_vb - > add_child ( bottom_panel_hb ) ;
2014-02-10 02:10:30 +01:00
2018-07-16 03:38:14 +02:00
bottom_panel_hb_editors = memnew ( HBoxContainer ) ;
bottom_panel_hb_editors - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
bottom_panel_hb - > add_child ( bottom_panel_hb_editors ) ;
2019-07-22 23:14:51 +02:00
2019-12-24 01:20:54 +01:00
VBoxContainer * version_info_vbc = memnew ( VBoxContainer ) ;
bottom_panel_hb - > add_child ( version_info_vbc ) ;
// Add a dummy control node for vertical spacing.
Control * v_spacer = memnew ( Control ) ;
version_info_vbc - > add_child ( v_spacer ) ;
version_btn = memnew ( LinkButton ) ;
version_btn - > set_text ( VERSION_FULL_CONFIG ) ;
String hash = String ( VERSION_HASH ) ;
if ( hash . length ( ) ! = 0 ) {
2021-06-07 23:51:18 +02:00
hash = " " + vformat ( " [%s] " , hash . left ( 9 ) ) ;
2019-12-24 01:20:54 +01:00
}
// Set the text to copy in metadata as it slightly differs from the button's text.
version_btn - > set_meta ( META_TEXT_TO_COPY , " v " VERSION_FULL_BUILD + hash ) ;
2019-07-22 23:14:51 +02:00
// Fade out the version label to be less prominent, but still readable
2019-12-24 01:20:54 +01:00
version_btn - > set_self_modulate ( Color ( 1 , 1 , 1 , 0.65 ) ) ;
version_btn - > set_underline_mode ( LinkButton : : UNDERLINE_MODE_ON_HOVER ) ;
version_btn - > set_tooltip ( TTR ( " Click to copy. " ) ) ;
version_btn - > connect ( " pressed " , this , " _version_button_pressed " ) ;
version_info_vbc - > add_child ( version_btn ) ;
// Add a dummy control node for horizontal spacing.
Control * h_spacer = memnew ( Control ) ;
bottom_panel_hb - > add_child ( h_spacer ) ;
2019-07-22 23:14:51 +02:00
2018-07-16 03:38:14 +02:00
bottom_panel_raise = memnew ( ToolButton ) ;
bottom_panel_raise - > set_icon ( gui_base - > get_icon ( " ExpandBottomDock " , " EditorIcons " ) ) ;
bottom_panel_raise - > set_shortcut ( ED_SHORTCUT ( " editor/bottom_panel_expand " , TTR ( " Expand Bottom Panel " ) , KEY_MASK_SHIFT | KEY_F12 ) ) ;
bottom_panel_hb - > add_child ( bottom_panel_raise ) ;
bottom_panel_raise - > hide ( ) ;
bottom_panel_raise - > set_toggle_mode ( true ) ;
bottom_panel_raise - > connect ( " toggled " , this , " _bottom_panel_raise_toggled " ) ;
2017-03-05 16:44:50 +01:00
log = memnew ( EditorLog ) ;
2018-03-11 14:20:32 +01:00
ToolButton * output_button = add_bottom_panel_item ( TTR ( " Output " ) , log ) ;
log - > set_tool_button ( output_button ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
old_split_ofs = 0 ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
center_split - > connect ( " resized " , this , " _vp_resized " ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
orphan_resources = memnew ( OrphanResourcesDialog ) ;
2015-11-29 05:08:31 +01:00
gui_base - > add_child ( orphan_resources ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
confirmation = memnew ( ConfirmationDialog ) ;
2014-02-10 02:10:30 +01:00
gui_base - > add_child ( confirmation ) ;
2017-03-05 16:44:50 +01:00
confirmation - > connect ( " confirmed " , this , " _menu_confirm_current " ) ;
2014-02-10 02:10:30 +01:00
2017-06-21 06:15:39 +02:00
save_confirmation = memnew ( ConfirmationDialog ) ;
save_confirmation - > add_button ( TTR ( " Don't Save " ) , OS : : get_singleton ( ) - > get_swap_ok_cancel ( ) , " discard " ) ;
gui_base - > add_child ( save_confirmation ) ;
save_confirmation - > connect ( " confirmed " , this , " _menu_confirm_current " ) ;
save_confirmation - > connect ( " custom_action " , this , " _discard_changes " ) ;
2019-04-07 20:46:52 +02:00
custom_build_manage_templates = memnew ( ConfirmationDialog ) ;
custom_build_manage_templates - > set_text ( TTR ( " Android build template is missing, please install relevant templates. " ) ) ;
custom_build_manage_templates - > get_ok ( ) - > set_text ( TTR ( " Manage Templates " ) ) ;
2021-07-15 15:12:56 +02:00
custom_build_manage_templates - > add_button ( TTR ( " Install from file " ) ) - > connect ( " pressed " , this , " _menu_option " , varray ( SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE ) ) ;
2019-04-07 20:46:52 +02:00
custom_build_manage_templates - > connect ( " confirmed " , this , " _menu_option " , varray ( SETTINGS_MANAGE_EXPORT_TEMPLATES ) ) ;
gui_base - > add_child ( custom_build_manage_templates ) ;
2021-07-15 15:12:56 +02:00
file_android_build_source = memnew ( EditorFileDialog ) ;
file_android_build_source - > set_title ( TTR ( " Select android sources file " ) ) ;
file_android_build_source - > set_access ( EditorFileDialog : : ACCESS_FILESYSTEM ) ;
file_android_build_source - > set_mode ( EditorFileDialog : : MODE_OPEN_FILE ) ;
file_android_build_source - > add_filter ( " *.zip " ) ;
file_android_build_source - > connect ( " file_selected " , this , " _android_build_source_selected " ) ;
gui_base - > add_child ( file_android_build_source ) ;
2019-04-07 20:46:52 +02:00
install_android_build_template = memnew ( ConfirmationDialog ) ;
2019-08-27 13:07:24 +02:00
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 \" . \n You can then apply modifications and build your own custom APK on export (adding modules, changing the AndroidManifest.xml, etc.). \n Note 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. " ) ) ;
2019-04-07 20:46:52 +02:00
install_android_build_template - > get_ok ( ) - > set_text ( TTR ( " Install " ) ) ;
install_android_build_template - > connect ( " confirmed " , this , " _menu_confirm_current " ) ;
gui_base - > add_child ( install_android_build_template ) ;
remove_android_build_template = memnew ( ConfirmationDialog ) ;
2019-08-27 13:07:24 +02:00
remove_android_build_template - > set_text ( TTR ( " The Android build template is already installed in this project and it won't be overwritten. \n Remove the \" res://android/build \" directory manually before attempting this operation again. " ) ) ;
2019-04-07 20:46:52 +02:00
remove_android_build_template - > get_ok ( ) - > set_text ( TTR ( " Show in File Manager " ) ) ;
remove_android_build_template - > connect ( " confirmed " , this , " _menu_option " , varray ( FILE_EXPLORE_ANDROID_BUILD_TEMPLATES ) ) ;
gui_base - > add_child ( remove_android_build_template ) ;
2017-11-10 23:45:08 +01:00
file_templates = memnew ( EditorFileDialog ) ;
2016-05-19 00:08:12 +02:00
file_templates - > set_title ( TTR ( " Import Templates From ZIP File " ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
gui_base - > add_child ( file_templates ) ;
2017-11-10 23:45:08 +01:00
file_templates - > set_mode ( EditorFileDialog : : MODE_OPEN_FILE ) ;
file_templates - > set_access ( EditorFileDialog : : ACCESS_FILESYSTEM ) ;
2014-02-10 02:10:30 +01:00
file_templates - > clear_filters ( ) ;
2019-12-16 06:18:44 +01:00
file_templates - > add_filter ( " *.tpz ; " + TTR ( " Template Package " ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
file = memnew ( EditorFileDialog ) ;
2014-02-10 02:10:30 +01:00
gui_base - > add_child ( file ) ;
file - > set_current_dir ( " res:// " ) ;
2017-11-10 23:45:08 +01:00
file_export_lib = memnew ( EditorFileDialog ) ;
2016-05-04 03:25:37 +02:00
file_export_lib - > set_title ( TTR ( " Export Library " ) ) ;
2017-11-10 23:45:08 +01:00
file_export_lib - > set_mode ( EditorFileDialog : : MODE_SAVE_FILE ) ;
2017-03-05 16:44:50 +01:00
file_export_lib - > connect ( " file_selected " , this , " _dialog_action " ) ;
2019-07-04 17:30:44 +02:00
file_export_lib_merge = memnew ( CheckBox ) ;
2016-05-04 03:25:37 +02:00
file_export_lib_merge - > set_text ( TTR ( " Merge With Existing " ) ) ;
2021-11-21 21:29:34 +01:00
file_export_lib_merge - > set_h_size_flags ( Control : : SIZE_SHRINK_CENTER ) ;
2014-02-10 02:10:30 +01:00
file_export_lib_merge - > set_pressed ( true ) ;
file_export_lib - > get_vbox ( ) - > add_child ( file_export_lib_merge ) ;
2021-09-01 01:17:33 +02:00
file_export_lib_apply_xforms = memnew ( CheckBox ) ;
file_export_lib_apply_xforms - > set_text ( TTR ( " Apply MeshInstance Transforms " ) ) ;
2021-11-21 21:29:34 +01:00
file_export_lib_apply_xforms - > set_h_size_flags ( Control : : SIZE_SHRINK_CENTER ) ;
2021-09-01 01:17:33 +02:00
file_export_lib_apply_xforms - > set_pressed ( false ) ;
file_export_lib - > get_vbox ( ) - > add_child ( file_export_lib_apply_xforms ) ;
2014-02-10 02:10:30 +01:00
gui_base - > add_child ( file_export_lib ) ;
2017-11-10 23:45:08 +01:00
file_script = memnew ( EditorFileDialog ) ;
2016-05-04 03:25:37 +02:00
file_script - > set_title ( TTR ( " Open & Run a Script " ) ) ;
2017-11-10 23:45:08 +01:00
file_script - > set_access ( EditorFileDialog : : ACCESS_FILESYSTEM ) ;
file_script - > set_mode ( EditorFileDialog : : MODE_OPEN_FILE ) ;
2014-02-21 03:01:44 +01:00
List < String > sexts ;
2017-03-05 16:44:50 +01:00
ResourceLoader : : get_recognized_extensions_for_type ( " Script " , & sexts ) ;
for ( List < String > : : Element * E = sexts . front ( ) ; E ; E = E - > next ( ) ) {
file_script - > add_filter ( " *. " + E - > get ( ) ) ;
2014-02-21 03:01:44 +01:00
}
gui_base - > add_child ( file_script ) ;
2017-03-05 16:44:50 +01:00
file_script - > connect ( " file_selected " , this , " _dialog_action " ) ;
2014-02-21 03:01:44 +01:00
2017-03-05 16:44:50 +01:00
file_menu - > get_popup ( ) - > connect ( " id_pressed " , this , " _menu_option " ) ;
2019-04-10 17:21:26 +02:00
file_menu - > connect ( " about_to_show " , this , " _update_file_menu_opened " ) ;
file_menu - > get_popup ( ) - > connect ( " popup_hide " , this , " _update_file_menu_closed " ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
settings_menu - > get_popup ( ) - > connect ( " id_pressed " , this , " _menu_option " ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
file - > connect ( " file_selected " , this , " _dialog_action " ) ;
file_templates - > connect ( " file_selected " , this , " _dialog_action " ) ;
2016-01-18 00:03:57 +01:00
2018-06-07 17:46:14 +02:00
preview_gen = memnew ( AudioStreamPreviewGenerator ) ;
add_child ( preview_gen ) ;
2014-02-10 02:10:30 +01:00
//plugin stuff
2017-03-05 16:44:50 +01:00
file_server = memnew ( EditorFileServer ) ;
2016-01-18 00:03:57 +01:00
2021-02-11 01:08:49 +01:00
disk_changed = memnew ( ConfirmationDialog ) ;
{
VBoxContainer * vbc = memnew ( VBoxContainer ) ;
disk_changed - > add_child ( vbc ) ;
Label * dl = memnew ( Label ) ;
dl - > set_text ( TTR ( " The following files are newer on disk. \n What action should be taken? " ) ) ;
vbc - > add_child ( dl ) ;
disk_changed_list = memnew ( Tree ) ;
vbc - > add_child ( disk_changed_list ) ;
disk_changed_list - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
disk_changed - > connect ( " confirmed " , this , " _reload_modified_scenes " ) ;
disk_changed - > connect ( " confirmed " , this , " _reload_project_settings " ) ;
disk_changed - > get_ok ( ) - > set_text ( TTR ( " Reload " ) ) ;
disk_changed - > add_button ( TTR ( " Resave " ) , ! OS : : get_singleton ( ) - > get_swap_ok_cancel ( ) , " resave " ) ;
disk_changed - > connect ( " custom_action " , this , " _resave_scenes " ) ;
}
gui_base - > add_child ( disk_changed ) ;
2017-03-05 16:44:50 +01:00
add_editor_plugin ( memnew ( AnimationPlayerEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( CanvasItemEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( SpatialEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( ScriptEditorPlugin ( this ) ) ) ;
2017-01-21 23:00:25 +01:00
2017-01-25 18:30:40 +01:00
EditorAudioBuses * audio_bus_editor = EditorAudioBuses : : register_editor ( ) ;
2017-01-21 23:00:25 +01:00
2016-08-03 00:11:05 +02:00
ScriptTextEditor : : register_editor ( ) ; //register one for text scripts
2018-05-28 17:52:28 +02:00
TextEditor : : register_editor ( ) ;
2016-08-03 00:11:05 +02:00
2022-06-29 19:27:27 +02:00
if ( AssetLibraryEditorPlugin : : is_available ( ) ) {
2017-03-05 16:44:50 +01:00
add_editor_plugin ( memnew ( AssetLibraryEditorPlugin ( this ) ) ) ;
2016-06-10 03:47:43 +02:00
} else {
2022-07-08 15:25:54 +02:00
print_verbose ( " Asset Library not available (due to using Web editor, or SSL support disabled). " ) ;
2016-06-10 03:47:43 +02:00
}
2017-08-26 15:32:15 +02:00
//add interface before adding plugins
editor_interface = memnew ( EditorInterface ) ;
add_child ( editor_interface ) ;
2016-01-18 00:03:57 +01:00
//more visually meaningful to have this later
raise_bottom_panel_item ( AnimationPlayerEditor : : singleton ) ;
2019-09-03 16:42:08 +02:00
add_editor_plugin ( VersionControlEditorPlugin : : get_singleton ( ) ) ;
2017-03-05 16:44:50 +01:00
add_editor_plugin ( memnew ( ShaderEditorPlugin ( this ) ) ) ;
2018-07-14 23:15:42 +02:00
add_editor_plugin ( memnew ( VisualShaderEditorPlugin ( this ) ) ) ;
2016-10-07 16:31:18 +02:00
2017-03-05 16:44:50 +01:00
add_editor_plugin ( memnew ( CameraEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( ThemeEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( MultiMeshEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( MeshInstanceEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( AnimationTreeEditorPlugin ( this ) ) ) ;
2018-08-20 18:38:18 +02:00
add_editor_plugin ( memnew ( AnimationTreePlayerEditorPlugin ( this ) ) ) ;
2017-08-15 16:41:17 +02:00
add_editor_plugin ( memnew ( MeshLibraryEditorPlugin ( this ) ) ) ;
2017-03-05 16:44:50 +01:00
add_editor_plugin ( memnew ( StyleBoxEditorPlugin ( this ) ) ) ;
2018-02-21 13:38:21 +01:00
add_editor_plugin ( memnew ( SpriteEditorPlugin ( this ) ) ) ;
2018-02-21 21:23:27 +01:00
add_editor_plugin ( memnew ( Skeleton2DEditorPlugin ( this ) ) ) ;
2017-04-07 04:36:37 +02:00
add_editor_plugin ( memnew ( ParticlesEditorPlugin ( this ) ) ) ;
2019-03-19 17:28:57 +01:00
add_editor_plugin ( memnew ( CPUParticles2DEditorPlugin ( this ) ) ) ;
2018-07-07 01:21:13 +02:00
add_editor_plugin ( memnew ( CPUParticlesEditorPlugin ( this ) ) ) ;
2017-03-05 16:44:50 +01:00
add_editor_plugin ( memnew ( ResourcePreloaderEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( ItemListEditorPlugin ( this ) ) ) ;
2018-04-28 02:52:15 +02:00
add_editor_plugin ( memnew ( Polygon3DEditorPlugin ( this ) ) ) ;
2017-03-05 16:44:50 +01:00
add_editor_plugin ( memnew ( CollisionPolygon2DEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( TileSetEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( TileMapEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( SpriteFramesEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( TextureRegionEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( Particles2DEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( GIProbeEditorPlugin ( this ) ) ) ;
2017-12-14 12:59:46 +01:00
add_editor_plugin ( memnew ( BakedLightmapEditorPlugin ( this ) ) ) ;
2021-02-04 11:43:08 +01:00
add_editor_plugin ( memnew ( RoomManagerEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( RoomEditorPlugin ( this ) ) ) ;
2021-08-05 16:44:43 +02:00
add_editor_plugin ( memnew ( OccluderEditorPlugin ( this ) ) ) ;
2021-07-16 10:15:14 +02:00
add_editor_plugin ( memnew ( PortalEditorPlugin ( this ) ) ) ;
2022-12-12 04:38:08 +01:00
add_editor_plugin ( memnew ( PackedSceneEditorPlugin ( this ) ) ) ;
2017-03-05 16:44:50 +01:00
add_editor_plugin ( memnew ( Path2DEditorPlugin ( this ) ) ) ;
2017-05-25 00:11:20 +02:00
add_editor_plugin ( memnew ( PathEditorPlugin ( this ) ) ) ;
2017-03-05 16:44:50 +01:00
add_editor_plugin ( memnew ( Line2DEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( Polygon2DEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( LightOccluder2DEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( NavigationPolygonEditorPlugin ( this ) ) ) ;
2017-06-13 23:47:34 +02:00
add_editor_plugin ( memnew ( GradientEditorPlugin ( this ) ) ) ;
2017-03-05 16:44:50 +01:00
add_editor_plugin ( memnew ( CollisionShape2DEditorPlugin ( this ) ) ) ;
2017-04-30 16:27:10 +02:00
add_editor_plugin ( memnew ( CurveEditorPlugin ( this ) ) ) ;
2017-03-05 16:44:50 +01:00
add_editor_plugin ( memnew ( TextureEditorPlugin ( this ) ) ) ;
2018-07-16 09:30:27 +02:00
add_editor_plugin ( memnew ( AudioStreamEditorPlugin ( this ) ) ) ;
2018-02-21 13:38:21 +01:00
add_editor_plugin ( memnew ( AudioBusesEditorPlugin ( audio_bus_editor ) ) ) ;
2017-10-03 18:49:32 +02:00
add_editor_plugin ( memnew ( SkeletonEditorPlugin ( this ) ) ) ;
2017-10-03 18:49:32 +02:00
add_editor_plugin ( memnew ( SkeletonIKEditorPlugin ( this ) ) ) ;
2017-10-03 18:49:32 +02:00
add_editor_plugin ( memnew ( PhysicalBonePlugin ( this ) ) ) ;
2019-03-04 19:52:39 +01:00
add_editor_plugin ( memnew ( MeshEditorPlugin ( this ) ) ) ;
add_editor_plugin ( memnew ( MaterialEditorPlugin ( this ) ) ) ;
2021-03-21 22:33:17 +01:00
add_editor_plugin ( memnew ( ViewportPreviewEditorPlugin ( this ) ) ) ;
2022-03-18 05:50:34 +01:00
add_editor_plugin ( memnew ( GradientTexture2DEditorPlugin ( this ) ) ) ;
2022-03-20 04:20:01 +01:00
add_editor_plugin ( memnew ( RayCast2DEditorPlugin ( this ) ) ) ;
2022-03-31 03:25:14 +02:00
add_editor_plugin ( memnew ( BitMapEditorPlugin ( this ) ) ) ;
2017-08-26 17:46:49 +02:00
2021-05-05 12:44:11 +02:00
for ( int i = 0 ; i < EditorPlugins : : get_plugin_count ( ) ; i + + ) {
2017-03-05 16:44:50 +01:00
add_editor_plugin ( EditorPlugins : : create ( i , this ) ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < plugin_init_callback_count ; i + + ) {
2016-08-07 00:00:54 +02:00
plugin_init_callbacks [ i ] ( ) ;
}
2015-05-31 06:59:42 +02:00
2017-06-09 05:23:50 +02:00
resource_preview - > add_preview_generator ( Ref < EditorTexturePreviewPlugin > ( memnew ( EditorTexturePreviewPlugin ) ) ) ;
2020-06-27 22:03:20 +02:00
resource_preview - > add_preview_generator ( Ref < EditorImagePreviewPlugin > ( memnew ( EditorImagePreviewPlugin ) ) ) ;
2017-06-09 05:23:50 +02:00
resource_preview - > add_preview_generator ( Ref < EditorPackedScenePreviewPlugin > ( memnew ( EditorPackedScenePreviewPlugin ) ) ) ;
resource_preview - > add_preview_generator ( Ref < EditorMaterialPreviewPlugin > ( memnew ( EditorMaterialPreviewPlugin ) ) ) ;
resource_preview - > add_preview_generator ( Ref < EditorScriptPreviewPlugin > ( memnew ( EditorScriptPreviewPlugin ) ) ) ;
2018-06-07 17:46:14 +02:00
resource_preview - > add_preview_generator ( Ref < EditorAudioStreamPreviewPlugin > ( memnew ( EditorAudioStreamPreviewPlugin ) ) ) ;
2017-06-09 05:23:50 +02:00
resource_preview - > add_preview_generator ( Ref < EditorMeshPreviewPlugin > ( memnew ( EditorMeshPreviewPlugin ) ) ) ;
resource_preview - > add_preview_generator ( Ref < EditorBitmapPreviewPlugin > ( memnew ( EditorBitmapPreviewPlugin ) ) ) ;
2018-04-16 05:00:56 +02:00
resource_preview - > add_preview_generator ( Ref < EditorFontPreviewPlugin > ( memnew ( EditorFontPreviewPlugin ) ) ) ;
2022-11-22 06:25:54 +01:00
resource_preview - > add_preview_generator ( Ref < EditorGradientPreviewPlugin > ( memnew ( EditorGradientPreviewPlugin ) ) ) ;
2016-08-07 00:00:54 +02:00
2017-09-22 14:20:28 +02:00
{
Ref < SpatialMaterialConversionPlugin > spatial_mat_convert ;
spatial_mat_convert . instance ( ) ;
resource_conversion_plugins . push_back ( spatial_mat_convert ) ;
2017-10-12 13:12:50 +02:00
2017-11-14 19:44:51 +01:00
Ref < CanvasItemMaterialConversionPlugin > canvas_item_mat_convert ;
canvas_item_mat_convert . instance ( ) ;
resource_conversion_plugins . push_back ( canvas_item_mat_convert ) ;
2017-10-12 13:12:50 +02:00
Ref < ParticlesMaterialConversionPlugin > particles_mat_convert ;
particles_mat_convert . instance ( ) ;
resource_conversion_plugins . push_back ( particles_mat_convert ) ;
2019-06-28 13:51:51 +02:00
Ref < VisualShaderConversionPlugin > vshader_convert ;
vshader_convert . instance ( ) ;
resource_conversion_plugins . push_back ( vshader_convert ) ;
2017-09-22 14:20:28 +02:00
}
2018-12-11 16:52:25 +01:00
update_spinner_step_msec = OS : : get_singleton ( ) - > get_ticks_msec ( ) ;
update_spinner_step_frame = Engine : : get_singleton ( ) - > get_frames_drawn ( ) ;
update_spinner_step = 0 ;
2014-02-10 02:10:30 +01:00
2021-05-04 16:00:45 +02:00
editor_plugin_screen = nullptr ;
2016-03-30 01:02:53 +02:00
editor_plugins_over = memnew ( EditorPluginList ) ;
2017-10-29 20:32:09 +01:00
editor_plugins_force_over = memnew ( EditorPluginList ) ;
2017-06-08 19:57:35 +02:00
editor_plugins_force_input_forwarding = memnew ( EditorPluginList ) ;
2014-02-10 02:10:30 +01:00
2017-12-15 12:38:24 +01:00
Ref < EditorExportTextSceneToBinaryPlugin > export_text_to_binary_plugin ;
export_text_to_binary_plugin . instance ( ) ;
EditorExport : : get_singleton ( ) - > add_export_plugin ( export_text_to_binary_plugin ) ;
2014-02-10 02:10:30 +01:00
_edit_current ( ) ;
2021-05-04 16:00:45 +02:00
current = nullptr ;
2018-11-18 15:17:04 +01:00
saving_resource = Ref < Resource > ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
reference_resource_mem = true ;
save_external_resources_mem = true ;
2014-02-10 02:10:30 +01:00
set_process ( true ) ;
2017-03-05 16:44:50 +01:00
open_imported = memnew ( ConfirmationDialog ) ;
2017-02-05 00:31:15 +01:00
open_imported - > get_ok ( ) - > set_text ( TTR ( " Open Anyway " ) ) ;
2017-08-23 22:25:14 +02:00
new_inherited_button = open_imported - > add_button ( TTR ( " New Inherited " ) , ! OS : : get_singleton ( ) - > get_swap_ok_cancel ( ) , " inherit " ) ;
2017-03-05 16:44:50 +01:00
open_imported - > connect ( " confirmed " , this , " _open_imported " ) ;
open_imported - > connect ( " custom_action " , this , " _inherit_imported " ) ;
2017-02-05 00:31:15 +01:00
gui_base - > add_child ( open_imported ) ;
2017-03-05 16:44:50 +01:00
saved_version = 1 ;
unsaved_cache = true ;
2021-05-04 16:00:45 +02:00
_last_instanced_scene = nullptr ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
quick_open = memnew ( EditorQuickOpen ) ;
2014-02-10 02:10:30 +01:00
gui_base - > add_child ( quick_open ) ;
2017-03-05 16:44:50 +01:00
quick_open - > connect ( " quick_open " , this , " _quick_opened " ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
quick_run = memnew ( EditorQuickOpen ) ;
2014-02-10 02:10:30 +01:00
gui_base - > add_child ( quick_run ) ;
2017-03-05 16:44:50 +01:00
quick_run - > connect ( " quick_open " , this , " _quick_run " ) ;
2014-02-10 02:10:30 +01:00
_update_recent_scenes ( ) ;
editor_data . restore_editor_global_states ( ) ;
2017-03-05 16:44:50 +01:00
convert_old = false ;
opening_prev = false ;
2014-02-10 02:10:30 +01:00
set_process_unhandled_input ( true ) ;
2017-03-05 16:44:50 +01:00
_playing_edited = false ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
load_errors = memnew ( RichTextLabel ) ;
load_error_dialog = memnew ( AcceptDialog ) ;
2014-02-10 02:10:30 +01:00
load_error_dialog - > add_child ( load_errors ) ;
2016-05-04 03:25:37 +02:00
load_error_dialog - > set_title ( TTR ( " Load Errors " ) ) ;
2016-06-28 00:59:33 +02:00
gui_base - > add_child ( load_error_dialog ) ;
2014-02-10 02:10:30 +01:00
2019-04-07 20:46:52 +02:00
execute_outputs = memnew ( RichTextLabel ) ;
2020-06-04 14:38:55 +02:00
execute_outputs - > set_selection_enabled ( true ) ;
2019-04-07 20:46:52 +02:00
execute_output_dialog = memnew ( AcceptDialog ) ;
execute_output_dialog - > add_child ( execute_outputs ) ;
2019-06-16 21:57:34 +02:00
execute_output_dialog - > set_title ( " " ) ;
2022-07-01 20:00:49 +02:00
// Prevent closing too fast and missing important information.
execute_output_dialog - > set_exclusive ( true ) ;
2019-04-07 20:46:52 +02:00
gui_base - > add_child ( execute_output_dialog ) ;
2017-03-05 16:44:50 +01:00
EditorFileSystem : : get_singleton ( ) - > connect ( " sources_changed " , this , " _sources_changed " ) ;
EditorFileSystem : : get_singleton ( ) - > connect ( " filesystem_changed " , this , " _fs_changed " ) ;
2017-08-31 23:57:03 +02:00
EditorFileSystem : : get_singleton ( ) - > connect ( " resources_reimported " , this , " _resources_reimported " ) ;
2018-11-21 01:47:48 +01:00
EditorFileSystem : : get_singleton ( ) - > connect ( " resources_reload " , this , " _resources_changed " ) ;
2014-02-10 02:10:30 +01:00
2018-02-25 17:04:16 +01:00
_build_icon_type_cache ( ) ;
2014-02-10 02:10:30 +01:00
2014-02-23 00:28:19 +01:00
Node : : set_human_readable_collision_renaming ( true ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
pick_main_scene = memnew ( ConfirmationDialog ) ;
2016-06-28 00:59:33 +02:00
gui_base - > add_child ( pick_main_scene ) ;
2017-08-23 22:25:14 +02:00
pick_main_scene - > get_ok ( ) - > set_text ( TTR ( " Select " ) ) ;
2017-03-05 16:44:50 +01:00
pick_main_scene - > connect ( " confirmed " , this , " _menu_option " , varray ( SETTINGS_PICK_MAIN_SCENE ) ) ;
2021-07-06 16:10:07 +02:00
select_current_scene_button = pick_main_scene - > add_button ( TTR ( " Select Current " ) , true , " select_current " ) ;
pick_main_scene - > connect ( " custom_action " , this , " _pick_main_scene_custom_action " ) ;
2015-06-14 03:12:53 +02:00
2021-05-05 12:44:11 +02:00
for ( int i = 0 ; i < _init_callbacks . size ( ) ; i + + ) {
2014-02-25 13:31:47 +01:00
_init_callbacks [ i ] ( ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2015-06-22 05:03:19 +02:00
editor_data . add_edited_scene ( - 1 ) ;
editor_data . set_edited_scene ( 0 ) ;
_update_scene_tabs ( ) ;
2017-07-23 16:44:42 +02:00
import_dock - > initialize_import_options ( ) ;
2016-06-13 15:10:50 +02:00
FileAccess : : set_file_close_fail_notify_callback ( _file_access_close_error_notify ) ;
2015-06-22 05:03:19 +02:00
2017-03-05 16:44:50 +01:00
waiting_for_first_scan = true ;
2017-03-06 20:11:56 +01:00
2017-11-14 23:02:31 +01:00
print_handler . printfunc = _print_handler ;
print_handler . userdata = this ;
add_print_handler ( & print_handler ) ;
2018-10-29 20:36:31 +01:00
ResourceSaver : : set_save_callback ( _resource_saved ) ;
ResourceLoader : : set_load_callback ( _resource_loaded ) ;
2018-06-11 07:53:25 +02:00
# ifdef OSX_ENABLED
ED_SHORTCUT ( " editor/editor_2d " , TTR ( " Open 2D Editor " ) , KEY_MASK_ALT | KEY_1 ) ;
ED_SHORTCUT ( " editor/editor_3d " , TTR ( " Open 3D Editor " ) , KEY_MASK_ALT | KEY_2 ) ;
ED_SHORTCUT ( " editor/editor_script " , TTR ( " Open Script Editor " ) , KEY_MASK_ALT | KEY_3 ) ;
2020-04-25 15:04:49 +02:00
ED_SHORTCUT ( " editor/editor_assetlib " , TTR ( " Open Asset Library " ) , KEY_MASK_ALT | KEY_4 ) ;
2018-06-11 07:53:25 +02:00
# else
2020-04-25 15:04:49 +02:00
// Use the Ctrl modifier so F2 can be used to rename nodes in the scene tree dock.
ED_SHORTCUT ( " editor/editor_2d " , TTR ( " Open 2D Editor " ) , KEY_MASK_CTRL | KEY_F1 ) ;
ED_SHORTCUT ( " editor/editor_3d " , TTR ( " Open 3D Editor " ) , KEY_MASK_CTRL | KEY_F2 ) ;
ED_SHORTCUT ( " editor/editor_script " , TTR ( " Open Script Editor " ) , KEY_MASK_CTRL | KEY_F3 ) ;
ED_SHORTCUT ( " editor/editor_assetlib " , TTR ( " Open Asset Library " ) , KEY_MASK_CTRL | KEY_F4 ) ;
2018-06-11 07:53:25 +02:00
# endif
2017-05-16 21:26:32 +02:00
ED_SHORTCUT ( " editor/editor_next " , TTR ( " Open the next Editor " ) ) ;
ED_SHORTCUT ( " editor/editor_prev " , TTR ( " Open the previous Editor " ) ) ;
2019-03-29 14:53:11 +01:00
screenshot_timer = memnew ( Timer ) ;
screenshot_timer - > set_one_shot ( true ) ;
screenshot_timer - > set_wait_time ( settings_menu - > get_popup ( ) - > get_submenu_popup_delay ( ) + 0.1f ) ;
screenshot_timer - > connect ( " timeout " , this , " _request_screenshot " ) ;
add_child ( screenshot_timer ) ;
screenshot_timer - > set_owner ( get_owner ( ) ) ;
2020-03-12 13:59:48 +01:00
String exec = OS : : get_singleton ( ) - > get_executable_path ( ) ;
EditorSettings : : get_singleton ( ) - > set_project_metadata ( " editor_metadata " , " executable_path " , exec ) ; // Save editor executable path for third-party tools
2023-01-22 19:42:34 +01:00
OS : : get_singleton ( ) - > benchmark_end_measure ( " editor " ) ;
2014-02-10 02:10:30 +01:00
}
2016-03-09 00:00:52 +01:00
EditorNode : : ~ EditorNode ( ) {
2018-05-15 22:12:35 +02:00
EditorInspector : : cleanup_plugins ( ) ;
2017-11-14 23:02:31 +01:00
remove_print_handler ( & print_handler ) ;
2017-03-05 16:44:50 +01:00
memdelete ( EditorHelp : : get_doc_data ( ) ) ;
2014-02-10 02:10:30 +01:00
memdelete ( editor_selection ) ;
2016-03-30 01:02:53 +02:00
memdelete ( editor_plugins_over ) ;
2017-10-29 20:32:09 +01:00
memdelete ( editor_plugins_force_over ) ;
2017-06-08 19:57:35 +02:00
memdelete ( editor_plugins_force_input_forwarding ) ;
2014-02-10 02:10:30 +01:00
memdelete ( file_server ) ;
2017-08-24 18:51:28 +02:00
memdelete ( progress_hb ) ;
2018-11-08 15:30:02 +01:00
2014-02-10 02:10:30 +01:00
EditorSettings : : destroy ( ) ;
}
2016-03-30 01:02:53 +02:00
/*
* EDITOR PLUGIN LIST
*/
void EditorPluginList : : make_visible ( bool p_visible ) {
2016-09-10 21:44:03 +02:00
for ( int i = 0 ; i < plugins_list . size ( ) ; i + + ) {
plugins_list [ i ] - > make_visible ( p_visible ) ;
2016-03-30 01:02:53 +02:00
}
}
2017-03-05 16:44:50 +01:00
void EditorPluginList : : edit ( Object * p_object ) {
2016-09-10 21:44:03 +02:00
for ( int i = 0 ; i < plugins_list . size ( ) ; i + + ) {
plugins_list [ i ] - > edit ( p_object ) ;
2016-03-30 01:02:53 +02:00
}
}
2017-10-15 22:33:25 +02:00
bool EditorPluginList : : forward_gui_input ( const Ref < InputEvent > & p_event ) {
2016-03-30 01:02:53 +02:00
bool discard = false ;
2016-09-10 21:44:03 +02:00
for ( int i = 0 ; i < plugins_list . size ( ) ; i + + ) {
2017-10-15 22:33:25 +02:00
if ( plugins_list [ i ] - > forward_canvas_gui_input ( p_event ) ) {
2016-09-10 21:44:03 +02:00
discard = true ;
2016-03-30 01:02:53 +02:00
}
}
2016-09-10 21:44:03 +02:00
2016-03-30 01:02:53 +02:00
return discard ;
}
2017-06-08 19:57:35 +02:00
bool EditorPluginList : : forward_spatial_gui_input ( Camera * p_camera , const Ref < InputEvent > & p_event , bool serve_when_force_input_enabled ) {
2016-03-30 01:02:53 +02:00
bool discard = false ;
2016-09-10 21:44:03 +02:00
for ( int i = 0 ; i < plugins_list . size ( ) ; i + + ) {
2017-06-08 19:57:35 +02:00
if ( ( ! serve_when_force_input_enabled ) & & plugins_list [ i ] - > is_input_event_forwarding_always_enabled ( ) ) {
continue ;
}
2017-01-08 20:28:12 +01:00
if ( plugins_list [ i ] - > forward_spatial_gui_input ( p_camera , p_event ) ) {
2016-09-10 21:44:03 +02:00
discard = true ;
2016-03-30 01:02:53 +02:00
}
}
2016-09-10 21:44:03 +02:00
2016-03-30 01:02:53 +02:00
return discard ;
}
2018-09-18 20:00:07 +02:00
void EditorPluginList : : forward_canvas_draw_over_viewport ( Control * p_overlay ) {
2016-09-10 21:44:03 +02:00
for ( int i = 0 ; i < plugins_list . size ( ) ; i + + ) {
2018-09-18 20:00:07 +02:00
plugins_list [ i ] - > forward_canvas_draw_over_viewport ( p_overlay ) ;
2017-10-29 20:32:09 +01:00
}
}
2018-09-18 20:00:07 +02:00
void EditorPluginList : : forward_canvas_force_draw_over_viewport ( Control * p_overlay ) {
2017-10-29 20:32:09 +01:00
for ( int i = 0 ; i < plugins_list . size ( ) ; i + + ) {
2018-09-18 20:00:07 +02:00
plugins_list [ i ] - > forward_canvas_force_draw_over_viewport ( p_overlay ) ;
}
}
void EditorPluginList : : forward_spatial_draw_over_viewport ( Control * p_overlay ) {
for ( int i = 0 ; i < plugins_list . size ( ) ; i + + ) {
plugins_list [ i ] - > forward_spatial_draw_over_viewport ( p_overlay ) ;
}
}
void EditorPluginList : : forward_spatial_force_draw_over_viewport ( Control * p_overlay ) {
for ( int i = 0 ; i < plugins_list . size ( ) ; i + + ) {
plugins_list [ i ] - > forward_spatial_force_draw_over_viewport ( p_overlay ) ;
2016-09-10 21:44:03 +02:00
}
}
2017-06-08 19:57:35 +02:00
void EditorPluginList : : add_plugin ( EditorPlugin * p_plugin ) {
plugins_list . push_back ( p_plugin ) ;
}
2019-02-25 16:49:06 +01:00
void EditorPluginList : : remove_plugin ( EditorPlugin * p_plugin ) {
plugins_list . erase ( p_plugin ) ;
}
2016-03-30 01:02:53 +02:00
bool EditorPluginList : : empty ( ) {
return plugins_list . empty ( ) ;
}
void EditorPluginList : : clear ( ) {
plugins_list . clear ( ) ;
}
EditorPluginList : : EditorPluginList ( ) {
}
EditorPluginList : : ~ EditorPluginList ( ) {
}