summaryrefslogtreecommitdiff
path: root/editor/editor_node.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/editor_node.cpp')
-rw-r--r--editor/editor_node.cpp479
1 files changed, 249 insertions, 230 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 6137617564..4cfa2d7338 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -32,25 +32,29 @@
#include "core/config/project_settings.h"
#include "core/core_bind.h"
+#include "core/extension/native_extension_manager.h"
#include "core/input/input.h"
#include "core/io/config_file.h"
+#include "core/io/file_access.h"
#include "core/io/image_loader.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/io/stream_peer_ssl.h"
#include "core/object/class_db.h"
#include "core/object/message_queue.h"
-#include "core/os/file_access.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
+#include "core/os/time.h"
#include "core/string/print_string.h"
#include "core/string/translation.h"
#include "core/version.h"
+#include "core/version_hash.gen.h"
#include "main/main.h"
#include "scene/gui/center_container.h"
#include "scene/gui/control.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/file_dialog.h"
+#include "scene/gui/link_button.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/panel.h"
#include "scene/gui/panel_container.h"
@@ -78,8 +82,10 @@
#include "editor/editor_inspector.h"
#include "editor/editor_layouts_dialog.h"
#include "editor/editor_log.h"
+#include "editor/editor_paths.h"
#include "editor/editor_plugin.h"
#include "editor/editor_properties.h"
+#include "editor/editor_resource_picker.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_run_native.h"
#include "editor/editor_run_script.h"
@@ -115,7 +121,6 @@
#include "editor/plugins/animation_tree_editor_plugin.h"
#include "editor/plugins/asset_library_editor_plugin.h"
#include "editor/plugins/audio_stream_editor_plugin.h"
-#include "editor/plugins/baked_lightmap_editor_plugin.h"
#include "editor/plugins/camera_3d_editor_plugin.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/collision_polygon_2d_editor_plugin.h"
@@ -128,13 +133,14 @@
#include "editor/plugins/editor_debugger_plugin.h"
#include "editor/plugins/editor_preview_plugins.h"
#include "editor/plugins/font_editor_plugin.h"
-#include "editor/plugins/gi_probe_editor_plugin.h"
#include "editor/plugins/gpu_particles_2d_editor_plugin.h"
#include "editor/plugins/gpu_particles_3d_editor_plugin.h"
#include "editor/plugins/gpu_particles_collision_sdf_editor_plugin.h"
#include "editor/plugins/gradient_editor_plugin.h"
+#include "editor/plugins/input_event_editor_plugin.h"
#include "editor/plugins/item_list_editor_plugin.h"
#include "editor/plugins/light_occluder_2d_editor_plugin.h"
+#include "editor/plugins/lightmap_gi_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"
@@ -168,10 +174,10 @@
#include "editor/plugins/texture_layered_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"
+#include "editor/plugins/tiles/tiles_editor_plugin.h"
#include "editor/plugins/version_control_editor_plugin.h"
#include "editor/plugins/visual_shader_editor_plugin.h"
+#include "editor/plugins/voxel_gi_editor_plugin.h"
#include "editor/progress_dialog.h"
#include "editor/project_export.h"
#include "editor/project_settings_editor.h"
@@ -184,6 +190,9 @@
EditorNode *EditorNode::singleton = nullptr;
+// 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";
+
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.
@@ -478,8 +487,8 @@ void EditorNode::_update_from_settings() {
RS::get_singleton()->environment_set_sdfgi_frames_to_converge(frames_to_converge);
RS::EnvironmentSDFGIRayCount ray_count = RS::EnvironmentSDFGIRayCount(int(GLOBAL_GET("rendering/global_illumination/sdfgi/probe_ray_count")));
RS::get_singleton()->environment_set_sdfgi_ray_count(ray_count);
- RS::GIProbeQuality gi_probe_quality = RS::GIProbeQuality(int(GLOBAL_GET("rendering/global_illumination/gi_probes/quality")));
- RS::get_singleton()->gi_probe_set_quality(gi_probe_quality);
+ RS::VoxelGIQuality voxel_gi_quality = RS::VoxelGIQuality(int(GLOBAL_GET("rendering/global_illumination/voxel_gi/quality")));
+ RS::get_singleton()->voxel_gi_set_quality(voxel_gi_quality);
RS::get_singleton()->environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth"));
RS::get_singleton()->environment_set_volumetric_fog_filter_active(bool(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter")));
RS::get_singleton()->canvas_set_shadow_texture_size(GLOBAL_GET("rendering/2d/shadow_atlas/size"));
@@ -583,8 +592,7 @@ void EditorNode::_notification(int p_what) {
_initializing_addons = false;
}
- RenderingServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport_rid(), true);
- RenderingServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport_rid(), true);
+ RenderingServer::get_singleton()->viewport_set_disable_2d(get_scene_root()->get_viewport_rid(), true);
RenderingServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(), true);
feature_profile_manager->notify_changed();
@@ -602,7 +610,7 @@ void EditorNode::_notification(int p_what) {
} break;
case NOTIFICATION_APPLICATION_FOCUS_IN: {
- // Restore the original FPS cap after focusing back on the editor
+ // Restore the original FPS cap after focusing back on the editor.
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec")));
EditorFileSystem::get_singleton()->scan_changes();
@@ -610,7 +618,12 @@ void EditorNode::_notification(int p_what) {
} break;
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
- // Set a low FPS cap to decrease CPU/GPU usage while the editor is unfocused
+ // 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.
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/unfocused_low_processor_mode_sleep_usec")));
} break;
@@ -624,7 +637,7 @@ void EditorNode::_notification(int p_what) {
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));
- theme = create_editor_theme(theme_base->get_theme());
+ theme = create_custom_theme(theme_base->get_theme());
theme_base->set_theme(theme);
gui_base->set_theme(theme);
@@ -695,11 +708,17 @@ void EditorNode::_notification(int p_what) {
p->set_item_icon(p->get_item_index(HELP_SEARCH), gui_base->get_theme_icon("HelpSearch", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_DOCS), gui_base->get_theme_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_QA), gui_base->get_theme_icon("Instance", "EditorIcons"));
- p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_theme_icon("Godot", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_REPORT_A_BUG), gui_base->get_theme_icon("Instance", "EditorIcons"));
+ p->set_item_icon(p->get_item_index(HELP_SUGGEST_A_FEATURE), gui_base->get_theme_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_SEND_DOCS_FEEDBACK), gui_base->get_theme_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_COMMUNITY), gui_base->get_theme_icon("Instance", "EditorIcons"));
p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_theme_icon("Godot", "EditorIcons"));
+ p->set_item_icon(p->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), gui_base->get_theme_icon("Heart", "EditorIcons"));
+
+ for (int i = 0; i < main_editor_buttons.size(); i++) {
+ main_editor_buttons.write[i]->add_theme_font_override("font", gui_base->get_theme_font("main_button_font", "EditorFonts"));
+ main_editor_buttons.write[i]->add_theme_font_size_override("font_size", gui_base->get_theme_font_size("main_button_font_size", "EditorFonts"));
+ }
_update_update_spinner();
} break;
@@ -734,6 +753,18 @@ void EditorNode::_on_plugin_ready(Object *p_script, const String &p_activate_nam
push_item(script.operator->());
}
+void EditorNode::_remove_plugin_from_enabled(const String &p_name) {
+ ProjectSettings *ps = ProjectSettings::get_singleton();
+ PackedStringArray 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);
+}
+
void EditorNode::_resources_changed(const Vector<String> &p_resources) {
List<Ref<Resource>> changed;
@@ -747,7 +778,7 @@ void EditorNode::_resources_changed(const Vector<String> &p_resources) {
if (!res->editor_can_reload_from_file()) {
continue;
}
- if (!res->get_path().is_resource_file() && !res->get_path().is_abs_path()) {
+ if (!res->get_path().is_resource_file() && !res->get_path().is_absolute_path()) {
continue;
}
if (!FileAccess::exists(res->get_path())) {
@@ -989,6 +1020,10 @@ void EditorNode::_reload_project_settings() {
void EditorNode::_vp_resized() {
}
+void EditorNode::_version_button_pressed() {
+ DisplayServer::get_singleton()->clipboard_set(version_btn->get_meta(META_TEXT_TO_COPY));
+}
+
void EditorNode::_node_renamed() {
if (get_inspector()) {
get_inspector()->update_tree();
@@ -1210,7 +1245,7 @@ void EditorNode::_get_scene_metadata(const String &p_file) {
String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
Ref<ConfigFile> cf;
- cf.instance();
+ cf.instantiate();
Error err = cf->load(path);
if (err != OK || !cf->has_section("editor_states")) {
@@ -1244,7 +1279,7 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) {
String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
Ref<ConfigFile> cf;
- cf.instance();
+ cf.instantiate();
Dictionary md;
@@ -1389,7 +1424,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
// 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();
+ img.instantiate();
img->create(1, 1, false, Image::FORMAT_RGB8);
} else if (c3d < c2d) {
Ref<ViewportTexture> viewport_texture = scene_root->get_texture();
@@ -1399,8 +1434,9 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
} else {
// 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.
+ // The preview will be generated if no feature profile is set (as the 3D editor is enabled by default).
Ref<EditorFeatureProfile> profile = feature_profile_manager->get_current_profile();
- if (profile.is_valid() && !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D)) {
+ if (!profile.is_valid() || !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D)) {
img = Node3DEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_texture()->get_image();
}
}
@@ -1435,7 +1471,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
img->convert(Image::FORMAT_RGB8);
//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 temp_path = EditorPaths::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);
@@ -1559,6 +1595,8 @@ void EditorNode::_save_scene(String p_file, int idx) {
return;
}
+ scene->propagate_notification(NOTIFICATION_EDITOR_PRE_SAVE);
+
editor_data.apply_changes_in_editors();
List<Ref<AnimatedValuesBackup>> anim_backups;
_reset_animation_players(scene, &anim_backups);
@@ -1571,16 +1609,16 @@ void EditorNode::_save_scene(String p_file, int idx) {
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
+ // old version still work for referencing changes in instantiated or inherited scenes
sdata = Ref<PackedScene>(Object::cast_to<PackedScene>(ResourceCache::get(p_file)));
if (sdata.is_valid()) {
sdata->recreate_state();
} else {
- sdata.instance();
+ sdata.instantiate();
}
} else {
- sdata.instance();
+ sdata.instantiate();
}
Error err = sdata->pack(scene);
@@ -1589,15 +1627,6 @@ void EditorNode::_save_scene(String p_file, int idx) {
return;
}
- // force creation of node path cache
- // (hacky but needed for the tree to update properly)
- Node *dummy_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
- if (!dummy_scene) {
- show_accept(TTR("Couldn't save scene. Likely dependencies (instances or inheritance) couldn't be satisfied."), TTR("OK"));
- return;
- }
- memdelete(dummy_scene);
-
int flg = 0;
if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources")) {
flg |= ResourceSaver::FLAG_COMPRESS;
@@ -1630,6 +1659,8 @@ void EditorNode::_save_scene(String p_file, int idx) {
} else {
_dialog_display_save_error(p_file, err);
}
+
+ scene->propagate_notification(NOTIFICATION_EDITOR_POST_SAVE);
}
void EditorNode::save_all_scenes() {
@@ -1794,28 +1825,6 @@ void EditorNode::_dialog_action(String p_file) {
}
} break;
- case FILE_EXPORT_TILESET: {
- Ref<TileSet> tileset;
- if (FileAccess::exists(p_file) && file_export_lib_merge->is_pressed()) {
- tileset = ResourceLoader::load(p_file, "TileSet");
-
- if (tileset.is_null()) {
- show_accept(TTR("Can't load TileSet for merging!"), TTR("OK"));
- return;
- }
-
- } else {
- tileset = Ref<TileSet>(memnew(TileSet));
- }
-
- TileSetEditor::update_library_file(editor_data.get_edited_scene_root(), tileset, true);
-
- Error err = ResourceSaver::save(p_file, tileset);
- if (err) {
- show_accept(TTR("Error saving TileSet!"), TTR("OK"));
- return;
- }
- } break;
case RESOURCE_SAVE:
case RESOURCE_SAVE_AS: {
@@ -1833,11 +1842,11 @@ void EditorNode::_dialog_action(String p_file) {
}
Ref<ConfigFile> config;
- config.instance();
+ config.instantiate();
Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
if (err == ERR_FILE_CANT_OPEN || err == ERR_FILE_NOT_FOUND) {
- config.instance(); // new config
+ config.instantiate(); // new config
} else if (err != OK) {
show_warning(TTR("An error occurred while trying to save the editor layout.\nMake sure the editor's user data path is writable."));
return;
@@ -1861,7 +1870,7 @@ void EditorNode::_dialog_action(String p_file) {
}
Ref<ConfigFile> config;
- config.instance();
+ config.instantiate();
Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
if (err != OK || !config->has_section(p_file)) {
@@ -2066,7 +2075,7 @@ void EditorNode::_edit_current() {
editable_warning = TTR("This resource belongs to a scene that was imported, so it's not editable.\nPlease read the documentation relevant to importing scenes to better understand this workflow.");
} else {
if ((!get_edited_scene() || get_edited_scene()->get_filename() != base_path) && ResourceLoader::get_resource_type(base_path) == "PackedScene") {
- editable_warning = TTR("This resource belongs to a scene that was instanced or inherited.\nChanges to it won't be kept when saving the current scene.");
+ editable_warning = TTR("This resource belongs to a scene that was instantiated or inherited.\nChanges to it won't be kept when saving the current scene.");
}
}
} else if (current_res->get_path().is_resource_file()) {
@@ -2151,9 +2160,14 @@ void EditorNode::_edit_current() {
if (!inspector_only) {
EditorPlugin *main_plugin = editor_data.get_editor(current_obj);
- for (int i = 0; i < editor_table.size(); i++) {
- if (editor_table[i] == main_plugin && !main_editor_buttons[i]->is_visible()) {
- main_plugin = nullptr; //if button is not visible, then no plugin active
+ 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;
}
}
@@ -2167,26 +2181,8 @@ void EditorNode::_edit_current() {
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
-
- if (!changing_scene) {
- if (editor_plugin_screen) {
- editor_plugin_screen->make_visible(false);
- }
- editor_plugin_screen = main_plugin;
- editor_plugin_screen->edit(current_obj);
-
- editor_plugin_screen->make_visible(true);
-
- 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());
- }
-
- for (int i = 0; i < editor_table.size(); i++) {
- main_editor_buttons[i]->set_pressed(editor_table[i] == main_plugin);
- }
- }
-
+ _editor_select(plugin_index);
+ main_plugin->edit(current_obj);
} else {
editor_plugin_screen->edit(current_obj);
}
@@ -2405,11 +2401,13 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
}
} break;
- case FILE_CLOSE_ALL_AND_QUIT:
- case FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER:
case FILE_CLOSE: {
+ _scene_tab_closed(editor_data.get_edited_scene());
+ } break;
+ case FILE_CLOSE_ALL_AND_QUIT:
+ case FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER: {
if (!p_confirmed) {
- tab_closing = p_option == FILE_CLOSE ? editor_data.get_edited_scene() : _next_unsaved_scene(false);
+ tab_closing = _next_unsaved_scene(false);
_scene_tab_changed(tab_closing);
if (unsaved_cache || p_option == FILE_CLOSE_ALL_AND_QUIT || p_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER) {
@@ -2422,8 +2420,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
break;
}
}
- } else if (p_option == FILE_CLOSE) {
- tab_closing = editor_data.get_edited_scene();
}
if (!editor_data.get_edited_scene_root(tab_closing)) {
// empty tab
@@ -2460,15 +2456,24 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
Node *scene = editor_data.get_edited_scene_root(scene_idx);
if (!scene) {
- int saved = _save_external_resources();
- String err_text;
+ 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();
if (saved > 0) {
- err_text = vformat(TTR("Saved %s modified resource(s)."), itos(saved));
- } else {
- err_text = TTR("A root node is required to save the scene.");
+ 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"));
}
- show_accept(err_text, TTR("OK"));
break;
}
@@ -2530,25 +2535,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
file_export_lib->set_title(TTR("Export Mesh Library"));
} break;
- case FILE_EXPORT_TILESET: {
- //Make sure that the scene has a root before trying to convert to tileset
- if (!editor_data.get_edited_scene_root()) {
- show_accept(TTR("This operation can't be done without a root node."), TTR("OK"));
- break;
- }
-
- List<String> extensions;
- Ref<TileSet> ml(memnew(TileSet));
- ResourceSaver::get_recognized_extensions(ml, &extensions);
- file_export_lib->clear_filters();
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- file_export_lib->add_filter("*." + E->get());
- }
-
- file_export_lib->popup_file_dialog();
- file_export_lib->set_title(TTR("Export Tile Set"));
-
- } break;
case FILE_EXTERNAL_OPEN_SCENE: {
if (unsaved_cache && !p_confirmed) {
@@ -2705,6 +2691,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES: {
OS::get_singleton()->shell_open("file://" + ProjectSettings::get_singleton()->get_resource_path().plus_file("android"));
} break;
+ case RUN_RELOAD_CURRENT_PROJECT: {
+ restart_editor();
+ } break;
case FILE_QUIT:
case RUN_PROJECT_MANAGER: {
if (!p_confirmed) {
@@ -2724,7 +2713,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
}
save_confirmation->get_ok_button()->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 the following scene(s) before opening Project Manager?")) + unsaved_scenes);
+ 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);
save_confirmation->popup_centered();
}
}
@@ -2755,10 +2744,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
settings_config_dialog->popup_edit_settings();
} break;
case SETTINGS_EDITOR_DATA_FOLDER: {
- OS::get_singleton()->shell_open(String("file://") + EditorSettings::get_singleton()->get_data_dir());
+ OS::get_singleton()->shell_open(String("file://") + EditorPaths::get_singleton()->get_data_dir());
} break;
case SETTINGS_EDITOR_CONFIG_FOLDER: {
- OS::get_singleton()->shell_open(String("file://") + EditorSettings::get_singleton()->get_settings_dir());
+ OS::get_singleton()->shell_open(String("file://") + EditorPaths::get_singleton()->get_config_dir());
} break;
case SETTINGS_MANAGE_EXPORT_TEMPLATES: {
export_template_manager->popup_manager();
@@ -2808,6 +2797,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case HELP_REPORT_A_BUG: {
OS::get_singleton()->shell_open("https://github.com/godotengine/godot/issues");
} break;
+ case HELP_SUGGEST_A_FEATURE: {
+ OS::get_singleton()->shell_open("https://github.com/godotengine/godot-proposals#readme");
+ } break;
case HELP_SEND_DOCS_FEEDBACK: {
OS::get_singleton()->shell_open("https://github.com/godotengine/godot-docs/issues");
} break;
@@ -2817,6 +2809,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case HELP_ABOUT: {
about->popup_centered(Size2(780, 500) * EDSCALE);
} break;
+ case HELP_SUPPORT_GODOT_DEVELOPMENT: {
+ OS::get_singleton()->shell_open("https://godotengine.org/donate");
+ } break;
case SET_VIDEO_DRIVER_SAVE_AND_RESTART: {
ProjectSettings::get_singleton()->set("rendering/driver/driver_name", video_driver_request);
@@ -2833,7 +2828,7 @@ void EditorNode::_request_screenshot() {
}
void EditorNode::_screenshot(bool p_use_utc) {
- String name = "editor_screenshot_" + OS::get_singleton()->get_iso_date_time(p_use_utc).replace(":", "") + ".png";
+ String name = "editor_screenshot_" + Time::get_singleton()->get_datetime_string_from_system(p_use_utc).replace(":", "") + ".png";
NodePath path = String("user://") + name;
_save_screenshot(path);
if (EditorSettings::get_singleton()->get("interface/editor/automatically_open_screenshots")) {
@@ -2899,7 +2894,7 @@ void EditorNode::_exit_editor() {
_save_docks();
// Dim the editor window while it's quitting to make it clearer that it's busy
- dim_editor(true, true);
+ dim_editor(true);
get_tree()->quit();
}
@@ -3065,6 +3060,9 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed
tb->set_icon(singleton->gui_base->get_theme_icon(p_editor->get_name(), "EditorIcons"));
}
+ tb->add_theme_font_override("font", singleton->gui_base->get_theme_font("main_button_font", "EditorFonts"));
+ tb->add_theme_font_size_override("font_size", singleton->gui_base->get_theme_font_size("main_button_font_size", "EditorFonts"));
+
tb->set_name(p_editor->get_name());
singleton->main_editor_buttons.push_back(tb);
singleton->main_editor_button_vb->add_child(tb);
@@ -3101,10 +3099,11 @@ void EditorNode::remove_editor_plugin(EditorPlugin *p_editor, bool p_config_chan
if (p_config_changed) {
p_editor->disable_plugin();
}
- singleton->editor_plugins_over->get_plugins_list().erase(p_editor);
+ 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);
singleton->remove_child(p_editor);
singleton->editor_data.remove_editor_plugin(p_editor);
- singleton->get_editor_plugins_force_input_forwarding()->remove_plugin(p_editor);
}
void EditorNode::_update_addon_config() {
@@ -3141,18 +3140,9 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled,
}
Ref<ConfigFile> cf;
- cf.instance();
+ cf.instantiate();
if (!DirAccess::exists(p_addon.get_base_dir())) {
- ProjectSettings *ps = ProjectSettings::get_singleton();
- PackedStringArray enabled_plugins = ps->get("editor_plugins/enabled");
- for (int i = 0; i < enabled_plugins.size(); ++i) {
- if (enabled_plugins.get(i) == p_addon) {
- enabled_plugins.remove(i);
- break;
- }
- }
- ps->set("editor_plugins/enabled", enabled_plugins);
- ps->save();
+ _remove_plugin_from_enabled(p_addon);
WARN_PRINT("Addon '" + p_addon + "' failed to load. No directory found. Removing from enabled plugins.");
return;
}
@@ -3182,7 +3172,8 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled,
// Errors in the script cause the base_type to be an empty string.
if (String(script->get_instance_base_type()) == "") {
- show_warning(vformat(TTR("Unable to load addon script from path: '%s' There seems to be an error in the code, please check the syntax."), script_path));
+ show_warning(vformat(TTR("Unable to load addon script from path: '%s'. This might be due to a code error in that script.\nDisabling the addon at '%s' to prevent further errors."), script_path, p_addon));
+ _remove_plugin_from_enabled(p_addon);
return;
}
@@ -3530,7 +3521,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
sdata->set_path(lpath, true); //take over path
}
- Node *new_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_MAIN);
+ Node *new_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_MAIN);
if (!new_scene) {
sdata.unref();
@@ -3594,11 +3585,11 @@ void EditorNode::open_request(const String &p_path) {
}
void EditorNode::request_instance_scene(const String &p_path) {
- scene_tree_dock->instance(p_path);
+ scene_tree_dock->instantiate(p_path);
}
-void EditorNode::request_instance_scenes(const Vector<String> &p_files) {
- scene_tree_dock->instance_scenes(p_files);
+void EditorNode::request_instantiate_scenes(const Vector<String> &p_files) {
+ scene_tree_dock->instantiate_scenes(p_files);
}
ImportDock *EditorNode::get_import_dock() {
@@ -3622,8 +3613,8 @@ void EditorNode::_inherit_request(String p_file) {
_dialog_action(p_file);
}
-void EditorNode::_instance_request(const Vector<String> &p_files) {
- request_instance_scenes(p_files);
+void EditorNode::_instantiate_request(const Vector<String> &p_files) {
+ request_instantiate_scenes(p_files);
}
void EditorNode::_close_messages() {
@@ -3745,6 +3736,7 @@ void EditorNode::register_editor_types() {
ResourceLoader::set_timestamp_on_load(true);
ResourceSaver::set_timestamp_on_save(true);
+ ClassDB::register_class<EditorPaths>();
ClassDB::register_class<EditorPlugin>();
ClassDB::register_class<EditorTranslationParserPlugin>();
ClassDB::register_class<EditorImportPlugin>();
@@ -3773,6 +3765,8 @@ void EditorNode::register_editor_types() {
ClassDB::register_class<ScriptCreateDialog>();
ClassDB::register_class<EditorFeatureProfile>();
ClassDB::register_class<EditorSpinSlider>();
+ ClassDB::register_class<EditorResourcePicker>();
+ ClassDB::register_class<EditorScriptPicker>();
ClassDB::register_class<EditorSceneImporterMesh>();
ClassDB::register_class<EditorSceneImporterMeshNode3D>();
@@ -3782,10 +3776,16 @@ void EditorNode::register_editor_types() {
ClassDB::register_class<EditorScenePostImport>();
//ClassDB::register_type<EditorImportExport>();
ClassDB::register_class<EditorDebuggerPlugin>();
+
+ NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
}
void EditorNode::unregister_editor_types() {
+ NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
_init_callbacks.clear();
+ if (EditorPaths::get_singleton()) {
+ EditorPaths::free();
+ }
}
void EditorNode::stop_child_process(OS::ProcessID p_pid) {
@@ -3875,6 +3875,21 @@ Ref<ImageTexture> EditorNode::_load_custom_class_icon(const String &p_path) cons
return nullptr;
}
+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());
+ }
+}
+
Ref<Texture2D> EditorNode::get_object_icon(const Object *p_object, const String &p_fallback) const {
ERR_FAIL_COND_V(!p_object || !gui_base, nullptr);
@@ -4351,7 +4366,9 @@ void EditorNode::_save_docks() {
return; //scanning, do not touch docks
}
Ref<ConfigFile> config;
- config.instance();
+ config.instantiate();
+ // Load and amend existing config if it exists.
+ config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
_save_docks_to_config(config, "docks");
_save_open_scenes_to_config(config, "EditorNode");
@@ -4414,7 +4431,7 @@ void EditorNode::_dock_split_dragged(int ofs) {
void EditorNode::_load_docks() {
Ref<ConfigFile> config;
- config.instance();
+ config.instantiate();
Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
if (err != OK) {
//no config
@@ -4647,7 +4664,7 @@ bool EditorNode::has_scenes_in_session() {
return false;
}
Ref<ConfigFile> config;
- config.instance();
+ config.instantiate();
Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
if (err != OK) {
return false;
@@ -4667,6 +4684,14 @@ bool EditorNode::ensure_main_scene(bool p_from_native) {
current_option = -1;
pick_main_scene->set_text(TTR("No main scene has ever been defined, select one?\nYou can change it later in \"Project Settings\" under the 'application' category."));
pick_main_scene->popup_centered();
+
+ 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);
+ }
+
return false;
}
@@ -4740,7 +4765,7 @@ void EditorNode::_update_layouts_menu() {
editor_layouts->add_shortcut(ED_SHORTCUT("layout/default", TTR("Default")), SETTINGS_LAYOUT_DEFAULT);
Ref<ConfigFile> config;
- config.instance();
+ config.instantiate();
Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
if (err != OK) {
return; //no config
@@ -4783,7 +4808,7 @@ void EditorNode::_layout_menu_option(int p_id) {
} break;
default: {
Ref<ConfigFile> config;
- config.instance();
+ config.instantiate();
Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
if (err != OK) {
return; //no config
@@ -4855,7 +4880,7 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) {
_scene_tab_closed(scene_tabs->get_hovered_tab());
}
} else {
- if ((mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_doubleclick()) || (mb->get_button_index() == MOUSE_BUTTON_MIDDLE && mb->is_pressed())) {
+ if ((mb->get_button_index() == MOUSE_BUTTON_LEFT && mb->is_double_click()) || (mb->get_button_index() == MOUSE_BUTTON_MIDDLE && mb->is_pressed())) {
_menu_option_confirm(FILE_NEW_SCENE, true);
}
}
@@ -5302,7 +5327,7 @@ void EditorNode::_file_access_close_error_notify(const String &p_str) {
void EditorNode::reload_scene(const String &p_path) {
/*
- * No longer necesary since scenes now reset and reload their internal resource if needed.
+ * No longer necessary since scenes now reset and reload their internal resource if needed.
//first of all, reload internal textures, materials, meshes, etc. as they might have changed on disk
List<Ref<Resource>> cached;
@@ -5334,7 +5359,7 @@ void EditorNode::reload_scene(const String &p_path) {
if (scene_idx == -1) {
if (get_edited_scene()) {
- //scene is not open, so at it might be instanced. We'll refresh the whole scene later.
+ //scene is not open, so at it might be instantiated. We'll refresh the whole scene later.
editor_data.get_undo_redo().clear_history();
}
return;
@@ -5406,15 +5431,9 @@ void EditorNode::_open_imported() {
load_scene(open_import_request, true, false, true, true);
}
-void EditorNode::dim_editor(bool p_dimming, bool p_force_dim) {
- // Dimming can be forced regardless of the editor setting, which is useful when quitting the editor.
- if ((p_force_dim || EditorSettings::get_singleton()->get("interface/editor/dim_editor_on_dialog_popup")) && p_dimming) {
- dimmed = true;
- gui_base->set_modulate(Color(0.5, 0.5, 0.5));
- } else {
- dimmed = false;
- gui_base->set_modulate(Color(1, 1, 1));
- }
+void EditorNode::dim_editor(bool p_dimming) {
+ dimmed = p_dimming;
+ gui_base->set_modulate(p_dimming ? Color(0.5, 0.5, 0.5) : Color(1, 1, 1));
}
bool EditorNode::is_editor_dimmed() const {
@@ -5559,6 +5578,8 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method("_screenshot", &EditorNode::_screenshot);
ClassDB::bind_method("_save_screenshot", &EditorNode::_save_screenshot);
+ ClassDB::bind_method("_version_button_pressed", &EditorNode::_version_button_pressed);
+
ADD_SIGNAL(MethodInfo("play_pressed"));
ADD_SIGNAL(MethodInfo("pause_pressed"));
ADD_SIGNAL(MethodInfo("stop_pressed"));
@@ -5695,34 +5716,10 @@ EditorNode::EditorNode() {
int display_scale = EditorSettings::get_singleton()->get("interface/editor/display_scale");
switch (display_scale) {
- case 0: {
+ case 0:
// Try applying a suitable display scale automatically.
- // The code below is adapted in `editor/editor_settings.cpp` and `editor/project_manager.cpp`.
- // Make sure to update those when modifying the code below.
-#ifdef OSX_ENABLED
- editor_set_scale(DisplayServer::get_singleton()->screen_get_max_scale());
-#else
- const int screen = DisplayServer::get_singleton()->window_get_current_screen();
- float scale;
- if (DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && DisplayServer::get_singleton()->screen_get_size(screen).y >= 1400) {
- // hiDPI display.
- scale = 2.0;
- } else if (DisplayServer::get_singleton()->screen_get_size(screen).y >= 1700) {
- // Likely a hiDPI display, but we aren't certain due to the returned DPI.
- // Use an intermediate scale to handle this situation.
- scale = 1.5;
- } else if (DisplayServer::get_singleton()->screen_get_size(screen).y <= 800) {
- // Small loDPI display. Use a smaller display scale so that editor elements fit more easily.
- // Icons won't look great, but this is better than having editor elements overflow from its window.
- scale = 0.75;
- } else {
- scale = 1.0;
- }
-
- editor_set_scale(scale);
-#endif
- } break;
-
+ editor_set_scale(EditorSettings::get_singleton()->get_auto_display_scale());
+ break;
case 1:
editor_set_scale(0.75);
break;
@@ -5759,87 +5756,87 @@ EditorNode::EditorNode() {
{ //register importers at the beginning, so dialogs are created with the right extensions
Ref<ResourceImporterTexture> import_texture;
- import_texture.instance();
+ import_texture.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(import_texture);
Ref<ResourceImporterLayeredTexture> import_cubemap;
- import_cubemap.instance();
+ import_cubemap.instantiate();
import_cubemap->set_mode(ResourceImporterLayeredTexture::MODE_CUBEMAP);
ResourceFormatImporter::get_singleton()->add_importer(import_cubemap);
Ref<ResourceImporterLayeredTexture> import_array;
- import_array.instance();
+ import_array.instantiate();
import_array->set_mode(ResourceImporterLayeredTexture::MODE_2D_ARRAY);
ResourceFormatImporter::get_singleton()->add_importer(import_array);
Ref<ResourceImporterLayeredTexture> import_cubemap_array;
- import_cubemap_array.instance();
+ import_cubemap_array.instantiate();
import_cubemap_array->set_mode(ResourceImporterLayeredTexture::MODE_CUBEMAP_ARRAY);
ResourceFormatImporter::get_singleton()->add_importer(import_cubemap_array);
Ref<ResourceImporterLayeredTexture> import_3d;
- import_3d.instance();
+ import_3d.instantiate();
import_3d->set_mode(ResourceImporterLayeredTexture::MODE_3D);
ResourceFormatImporter::get_singleton()->add_importer(import_3d);
Ref<ResourceImporterImage> import_image;
- import_image.instance();
+ import_image.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(import_image);
Ref<ResourceImporterTextureAtlas> import_texture_atlas;
- import_texture_atlas.instance();
+ import_texture_atlas.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(import_texture_atlas);
Ref<ResourceImporterCSVTranslation> import_csv_translation;
- import_csv_translation.instance();
+ import_csv_translation.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(import_csv_translation);
Ref<ResourceImporterWAV> import_wav;
- import_wav.instance();
+ import_wav.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(import_wav);
Ref<ResourceImporterOBJ> import_obj;
- import_obj.instance();
+ import_obj.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(import_obj);
Ref<ResourceImporterShaderFile> import_shader_file;
- import_shader_file.instance();
+ import_shader_file.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(import_shader_file);
Ref<ResourceImporterScene> import_scene;
- import_scene.instance();
+ import_scene.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(import_scene);
{
Ref<EditorSceneImporterCollada> import_collada;
- import_collada.instance();
+ import_collada.instantiate();
import_scene->add_importer(import_collada);
Ref<EditorOBJImporter> import_obj2;
- import_obj2.instance();
+ import_obj2.instantiate();
import_scene->add_importer(import_obj2);
Ref<EditorSceneImporterESCN> import_escn;
- import_escn.instance();
+ import_escn.instantiate();
import_scene->add_importer(import_escn);
}
Ref<ResourceImporterBitMap> import_bitmap;
- import_bitmap.instance();
+ import_bitmap.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(import_bitmap);
}
{
Ref<EditorInspectorDefaultPlugin> eidp;
- eidp.instance();
+ eidp.instantiate();
EditorInspector::add_inspector_plugin(eidp);
Ref<EditorInspectorRootMotionPlugin> rmp;
- rmp.instance();
+ rmp.instantiate();
EditorInspector::add_inspector_plugin(rmp);
Ref<EditorInspectorShaderModePlugin> smp;
- smp.instance();
+ smp.instantiate();
EditorInspector::add_inspector_plugin(smp);
}
@@ -5865,8 +5862,6 @@ EditorNode::EditorNode() {
register_exporters();
- GLOBAL_DEF("editor/run/main_run_args", "");
-
ClassDB::set_class_enabled("RootMotionView", true);
//defs here, use EDITOR_GET in logic
@@ -5877,6 +5872,7 @@ EditorNode::EditorNode() {
EDITOR_DEF("run/output/always_open_output_on_play", true);
EDITOR_DEF("run/output/always_close_output_on_stop", true);
EDITOR_DEF("run/auto_save/save_before_running", true);
+ EDITOR_DEF("interface/editor/save_on_focus_loss", false);
EDITOR_DEF_RST("interface/editor/save_each_scene_on_quit", true);
EDITOR_DEF("interface/editor/show_update_spinner", false);
EDITOR_DEF("interface/editor/update_continuously", false);
@@ -5890,7 +5886,7 @@ EditorNode::EditorNode() {
EDITOR_DEF("interface/inspector/horizontal_vector2_editing", false);
EDITOR_DEF("interface/inspector/horizontal_vector_types_editing", true);
EDITOR_DEF("interface/inspector/open_resources_in_current_inspector", true);
- EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "Script,MeshLibrary,TileSet");
+ EDITOR_DEF("interface/inspector/resources_to_open_in_new_inspector", "Script,MeshLibrary");
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));
EDITOR_DEF("interface/inspector/default_color_picker_shape", (int32_t)ColorPicker::SHAPE_VHS_CIRCLE);
@@ -6143,9 +6139,9 @@ EditorNode::EditorNode() {
scene_root_parent->set_v_size_flags(Control::SIZE_EXPAND_FILL);
scene_root = memnew(SubViewport);
- //scene_root->set_usage(Viewport::USAGE_2D); canvas BG mode prevents usage of this as 2D
+ scene_root->set_embed_subwindows_hint(true);
+ scene_root->set_disable_3d(true);
- RenderingServer::get_singleton()->viewport_set_hide_scenario(scene_root->get_viewport_rid(), true);
scene_root->set_disable_input(true);
scene_root->set_as_audio_listener_2d(true);
@@ -6219,8 +6215,8 @@ EditorNode::EditorNode() {
p = file_menu->get_popup();
- p->add_shortcut(ED_SHORTCUT("editor/new_scene", TTR("New Scene")), FILE_NEW_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/new_inherited_scene", TTR("New Inherited Scene...")), FILE_NEW_INHERITED_SCENE);
+ 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);
p->add_shortcut(ED_SHORTCUT("editor/open_scene", TTR("Open Scene..."), KEY_MASK_CMD + KEY_O), FILE_OPEN_SCENE);
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);
@@ -6242,7 +6238,6 @@ EditorNode::EditorNode() {
p->add_child(pm_export);
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);
pm_export->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option));
p->add_separator();
@@ -6300,6 +6295,7 @@ EditorNode::EditorNode() {
tool_menu->add_item(TTR("Orphan Resource Explorer..."), TOOLS_ORPHAN_RESOURCES);
p->add_separator();
+ p->add_item(TTR("Reload Current Project"), RUN_RELOAD_CURRENT_PROJECT);
#ifdef OSX_ENABLED
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);
#else
@@ -6389,13 +6385,15 @@ EditorNode::EditorNode() {
p->add_icon_shortcut(gui_base->get_theme_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_F1), HELP_SEARCH);
#endif
p->add_separator();
- p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/online_docs", TTR("Online Docs")), HELP_DOCS);
- p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/q&a", TTR("Q&A")), HELP_QA);
+ p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/online_docs", TTR("Online Documentation")), HELP_DOCS);
+ p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/q&a", TTR("Questions & Answers")), HELP_QA);
p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG);
+ p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/suggest_a_feature", TTR("Suggest a Feature")), HELP_SUGGEST_A_FEATURE);
p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK);
p->add_icon_shortcut(gui_base->get_theme_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/community", TTR("Community")), HELP_COMMUNITY);
p->add_separator();
- p->add_icon_shortcut(gui_base->get_theme_icon("Godot", "EditorIcons"), ED_SHORTCUT("editor/about", TTR("About")), HELP_ABOUT);
+ p->add_icon_shortcut(gui_base->get_theme_icon("Godot", "EditorIcons"), ED_SHORTCUT("editor/about", TTR("About Godot")), HELP_ABOUT);
+ p->add_icon_shortcut(gui_base->get_theme_icon("Heart", "EditorIcons"), ED_SHORTCUT("editor/support_development", TTR("Support Godot Development")), HELP_SUPPORT_GODOT_DEVELOPMENT);
HBoxContainer *play_hb = memnew(HBoxContainer);
menu_hb->add_child(play_hb);
@@ -6479,7 +6477,6 @@ EditorNode::EditorNode() {
// Toggle for video driver
video_driver = memnew(OptionButton);
- video_driver->set_flat(true);
video_driver->set_focus_mode(Control::FOCUS_NONE);
video_driver->connect("item_selected", callable_mp(this, &EditorNode::_video_driver_selected));
video_driver->add_theme_font_override("font", gui_base->get_theme_font("bold", "EditorFonts"));
@@ -6543,7 +6540,7 @@ EditorNode::EditorNode() {
filesystem_dock = memnew(FileSystemDock(this));
filesystem_dock->connect("inherit", callable_mp(this, &EditorNode::_inherit_request));
- filesystem_dock->connect("instance", callable_mp(this, &EditorNode::_instance_request));
+ filesystem_dock->connect("instance", callable_mp(this, &EditorNode::_instantiate_request));
filesystem_dock->connect("display_mode_changed", callable_mp(this, &EditorNode::_save_docks));
// Scene: Top left
@@ -6583,7 +6580,7 @@ EditorNode::EditorNode() {
const String docks_section = "docks";
overridden_default_layout = -1;
- default_layout.instance();
+ default_layout.instantiate();
// Dock numbers are based on DockSlot enum value + 1
default_layout->set_value(docks_section, "dock_3", "Scene,Import");
default_layout->set_value(docks_section, "dock_4", "FileSystem");
@@ -6617,11 +6614,31 @@ EditorNode::EditorNode() {
bottom_panel_hb_editors->set_h_size_flags(Control::SIZE_EXPAND_FILL);
bottom_panel_hb->add_child(bottom_panel_hb_editors);
- version_label = memnew(Label);
- version_label->set_text(VERSION_FULL_CONFIG);
+ 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) {
+ hash = " " + vformat("[%s]", hash.left(9));
+ }
+ // 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);
// Fade out the version label to be less prominent, but still readable
- version_label->set_self_modulate(Color(1, 1, 1, 0.6));
- bottom_panel_hb->add_child(version_label);
+ 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", callable_mp(this, &EditorNode::_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);
bottom_panel_raise = memnew(Button);
bottom_panel_raise->set_flat(true);
@@ -6795,12 +6812,11 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(ItemListEditorPlugin(this)));
add_editor_plugin(memnew(Polygon3DEditorPlugin(this)));
add_editor_plugin(memnew(CollisionPolygon2DEditorPlugin(this)));
- add_editor_plugin(memnew(TileSetEditorPlugin(this)));
- add_editor_plugin(memnew(TileMapEditorPlugin(this)));
+ add_editor_plugin(memnew(TilesEditorPlugin(this)));
add_editor_plugin(memnew(SpriteFramesEditorPlugin(this)));
add_editor_plugin(memnew(TextureRegionEditorPlugin(this)));
- add_editor_plugin(memnew(GIProbeEditorPlugin(this)));
- add_editor_plugin(memnew(BakedLightmapEditorPlugin(this)));
+ add_editor_plugin(memnew(VoxelGIEditorPlugin(this)));
+ add_editor_plugin(memnew(LightmapGIEditorPlugin(this)));
add_editor_plugin(memnew(OccluderInstance3DEditorPlugin(this)));
add_editor_plugin(memnew(Path2DEditorPlugin(this)));
add_editor_plugin(memnew(Path3DEditorPlugin(this)));
@@ -6824,6 +6840,7 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(MeshEditorPlugin(this)));
add_editor_plugin(memnew(MaterialEditorPlugin(this)));
add_editor_plugin(memnew(GPUParticlesCollisionSDFEditorPlugin(this)));
+ add_editor_plugin(memnew(InputEventEditorPlugin(this)));
for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) {
add_editor_plugin(EditorPlugins::create(i, this));
@@ -6845,31 +6862,31 @@ EditorNode::EditorNode() {
{
Ref<StandardMaterial3DConversionPlugin> spatial_mat_convert;
- spatial_mat_convert.instance();
+ spatial_mat_convert.instantiate();
resource_conversion_plugins.push_back(spatial_mat_convert);
Ref<CanvasItemMaterialConversionPlugin> canvas_item_mat_convert;
- canvas_item_mat_convert.instance();
+ canvas_item_mat_convert.instantiate();
resource_conversion_plugins.push_back(canvas_item_mat_convert);
Ref<ParticlesMaterialConversionPlugin> particles_mat_convert;
- particles_mat_convert.instance();
+ particles_mat_convert.instantiate();
resource_conversion_plugins.push_back(particles_mat_convert);
Ref<ProceduralSkyMaterialConversionPlugin> procedural_sky_mat_convert;
- procedural_sky_mat_convert.instance();
+ procedural_sky_mat_convert.instantiate();
resource_conversion_plugins.push_back(procedural_sky_mat_convert);
Ref<PanoramaSkyMaterialConversionPlugin> panorama_sky_mat_convert;
- panorama_sky_mat_convert.instance();
+ panorama_sky_mat_convert.instantiate();
resource_conversion_plugins.push_back(panorama_sky_mat_convert);
Ref<PhysicalSkyMaterialConversionPlugin> physical_sky_mat_convert;
- physical_sky_mat_convert.instance();
+ physical_sky_mat_convert.instantiate();
resource_conversion_plugins.push_back(physical_sky_mat_convert);
Ref<VisualShaderConversionPlugin> vshader_convert;
- vshader_convert.instance();
+ vshader_convert.instantiate();
resource_conversion_plugins.push_back(vshader_convert);
}
update_spinner_step_msec = OS::get_singleton()->get_ticks_msec();
@@ -6882,12 +6899,12 @@ EditorNode::EditorNode() {
editor_plugins_force_input_forwarding = memnew(EditorPluginList);
Ref<EditorExportTextSceneToBinaryPlugin> export_text_to_binary_plugin;
- export_text_to_binary_plugin.instance();
+ export_text_to_binary_plugin.instantiate();
EditorExport::get_singleton()->add_export_plugin(export_text_to_binary_plugin);
Ref<PackedSceneEditorTranslationParserPlugin> packed_scene_translation_parser_plugin;
- packed_scene_translation_parser_plugin.instance();
+ packed_scene_translation_parser_plugin.instantiate();
EditorTranslationParser::get_singleton()->add_parser(packed_scene_translation_parser_plugin, EditorTranslationParser::STANDARD);
_edit_current();
@@ -6908,7 +6925,7 @@ EditorNode::EditorNode() {
saved_version = 1;
unsaved_cache = true;
- _last_instanced_scene = nullptr;
+ _last_instantiated_scene = nullptr;
quick_open = memnew(EditorQuickOpen);
gui_base->add_child(quick_open);
@@ -6952,6 +6969,8 @@ EditorNode::EditorNode() {
gui_base->add_child(pick_main_scene);
pick_main_scene->get_ok_button()->set_text(TTR("Select"));
pick_main_scene->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_PICK_MAIN_SCENE));
+ select_current_scene_button = pick_main_scene->add_button(TTR("Select Current"), true, "select_current");
+ pick_main_scene->connect("custom_action", callable_mp(this, &EditorNode::_pick_main_scene_custom_action));
for (int i = 0; i < _init_callbacks.size(); i++) {
_init_callbacks[i]();