diff options
Diffstat (limited to 'editor/editor_node.cpp')
-rw-r--r-- | editor/editor_node.cpp | 203 |
1 files changed, 116 insertions, 87 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 9a188bbe38..a2231f4601 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -37,7 +37,7 @@ #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/io/stream_peer_tls.h" #include "core/object/class_db.h" #include "core/object/message_queue.h" #include "core/os/keyboard.h" @@ -170,6 +170,7 @@ #include "editor/plugins/mesh_instance_3d_editor_plugin.h" #include "editor/plugins/mesh_library_editor_plugin.h" #include "editor/plugins/multimesh_editor_plugin.h" +#include "editor/plugins/navigation_link_2d_editor_plugin.h" #include "editor/plugins/navigation_polygon_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h" #include "editor/plugins/occluder_instance_3d_editor_plugin.h" @@ -216,6 +217,8 @@ EditorNode *EditorNode::singleton = nullptr; static const String META_TEXT_TO_COPY = "text_to_copy"; void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames) { + ERR_FAIL_COND_MSG(p_full_paths.size() != r_filenames.size(), vformat("disambiguate_filenames requires two string vectors of same length (%d != %d).", p_full_paths.size(), r_filenames.size())); + // Keep track of a list of "index sets," i.e. sets of indices // within disambiguated_scene_names which contain the same name. Vector<RBSet<int>> index_sets; @@ -250,6 +253,10 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto full_path = full_path.substr(0, full_path.rfind(".")); } + // Normalize trailing slashes when normalizing directory names. + scene_name = scene_name.trim_suffix("/"); + full_path = full_path.trim_suffix("/"); + int scene_name_size = scene_name.size(); int full_path_size = full_path.size(); int difference = full_path_size - scene_name_size; @@ -292,17 +299,23 @@ void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vecto // and the scene name first to remove extensions so that this // comparison actually works. String path = p_full_paths[E->get()]; + + // Get rid of file extensions and res:// prefixes. + if (scene_name.rfind(".") >= 0) { + scene_name = scene_name.substr(0, scene_name.rfind(".")); + } 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, + // Normalize trailing slashes when normalizing directory names. + scene_name = scene_name.trim_suffix("/"); + path = path.trim_suffix("/"); + + // We can proceed if 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; @@ -354,7 +367,7 @@ void EditorNode::_update_scene_tabs() { scene_tabs->add_tab(disambiguated_scene_names[i] + (unsaved ? "(*)" : ""), icon); if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) { - DisplayServer::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), callable_mp(this, &EditorNode::_global_menu_scene), i); + DisplayServer::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), callable_mp(this, &EditorNode::_global_menu_scene), Callable(), i); } if (show_rb && editor_data.get_scene_root_script(i).is_valid()) { @@ -411,9 +424,6 @@ void EditorNode::_version_control_menu_option(int 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; } } @@ -492,10 +502,10 @@ void EditorNode::_update_from_settings() { } RS::DOFBokehShape dof_shape = RS::DOFBokehShape(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_shape"))); - RS::get_singleton()->camera_effects_set_dof_blur_bokeh_shape(dof_shape); + RS::get_singleton()->camera_attributes_set_dof_blur_bokeh_shape(dof_shape); RS::DOFBlurQuality dof_quality = RS::DOFBlurQuality(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_quality"))); bool dof_jitter = GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_use_jitter"); - RS::get_singleton()->camera_effects_set_dof_blur_quality(dof_quality, dof_jitter); + RS::get_singleton()->camera_attributes_set_dof_blur_quality(dof_quality, dof_jitter); RS::get_singleton()->environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/environment/ssao/quality"))), GLOBAL_GET("rendering/environment/ssao/half_size"), GLOBAL_GET("rendering/environment/ssao/adaptive_target"), GLOBAL_GET("rendering/environment/ssao/blur_passes"), GLOBAL_GET("rendering/environment/ssao/fadeout_from"), GLOBAL_GET("rendering/environment/ssao/fadeout_to")); RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/enabled"), GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/amount"), GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/limit")); bool glow_bicubic = int(GLOBAL_GET("rendering/environment/glow/upscale_mode")) > 0; @@ -511,13 +521,13 @@ void EditorNode::_update_from_settings() { float sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale"); RS::get_singleton()->sub_surface_scattering_set_scale(sss_scale, sss_depth_scale); - uint32_t directional_shadow_size = GLOBAL_GET("rendering/shadows/directional_shadow/size"); - uint32_t directional_shadow_16_bits = GLOBAL_GET("rendering/shadows/directional_shadow/16_bits"); + uint32_t directional_shadow_size = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/size"); + uint32_t directional_shadow_16_bits = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/16_bits"); RS::get_singleton()->directional_shadow_atlas_set_size(directional_shadow_size, directional_shadow_16_bits); - RS::ShadowQuality shadows_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/positional_shadow/soft_shadow_filter_quality"))); + RS::ShadowQuality shadows_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality"))); RS::get_singleton()->positional_soft_shadow_filter_set_quality(shadows_quality); - RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_filter_quality"))); + RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality(int(GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality"))); RS::get_singleton()->directional_soft_shadow_filter_set_quality(directional_shadow_quality); float probe_update_speed = GLOBAL_GET("rendering/lightmapping/probe_capture/update_speed"); RS::get_singleton()->lightmap_set_probe_capture_update_speed(probe_update_speed); @@ -544,6 +554,9 @@ void EditorNode::_update_from_settings() { Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_GET("rendering/2d/sdf/scale"))); scene_root->set_sdf_scale(sdf_scale); + Viewport::MSAA msaa = Viewport::MSAA(int(GLOBAL_GET("rendering/anti_aliasing/quality/msaa_2d"))); + scene_root->set_msaa_2d(msaa); + float mesh_lod_threshold = GLOBAL_GET("rendering/mesh_lod/lod_change/threshold_pixels"); scene_root->set_mesh_lod_threshold(mesh_lod_threshold); @@ -749,9 +762,8 @@ void EditorNode::_notification(int p_what) { gui_base->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Background"), SNAME("EditorStyles"))); scene_root_parent->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("Content"), SNAME("EditorStyles"))); - bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); - scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox(SNAME("SceneTabFG"), SNAME("EditorStyles"))); - scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox(SNAME("SceneTabBG"), SNAME("EditorStyles"))); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), SNAME("EditorStyles"))); + tabbar_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("tabbar_background"), SNAME("TabContainer"))); main_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); } @@ -781,6 +793,14 @@ void EditorNode::_notification(int p_what) { _build_icon_type_cache(); + if (write_movie_button->is_pressed()) { + launch_pad->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("LaunchPadMovieMode"), SNAME("EditorStyles"))); + write_movie_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("MovieWriterButtonPressed"), SNAME("EditorStyles"))); + } else { + launch_pad->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("LaunchPadNormal"), SNAME("EditorStyles"))); + write_movie_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("MovieWriterButtonNormal"), SNAME("EditorStyles"))); + } + play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons"))); play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons"))); @@ -1048,7 +1068,7 @@ void EditorNode::_sources_changed(bool p_exist) { // Reload the global shader variables, but this time // loading textures, as they are now properly imported. - RenderingServer::get_singleton()->global_shader_uniforms_load_settings(true); + RenderingServer::get_singleton()->global_shader_parameters_load_settings(true); // Start preview thread now that it's safe. if (!singleton->cmdline_export_mode) { @@ -1096,7 +1116,7 @@ void EditorNode::_scan_external_changes() { } } - String project_settings_path = ProjectSettings::get_singleton()->get_resource_path().plus_file("project.godot"); + String project_settings_path = ProjectSettings::get_singleton()->get_resource_path().path_join("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"); @@ -1314,7 +1334,7 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String file->set_current_file(p_resource->get_path().get_file()); } else { if (extensions.size()) { - String resource_name_snake_case = p_resource->get_class().camelcase_to_underscore(); + String resource_name_snake_case = p_resource->get_class().to_snake_case(); file->set_current_file("new_" + resource_name_snake_case + "." + preferred.front()->get().to_lower()); } else { file->set_current_file(String()); @@ -1331,7 +1351,7 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String } else if (preferred.size()) { String existing; if (extensions.size()) { - String resource_name_snake_case = p_resource->get_class().camelcase_to_underscore(); + String resource_name_snake_case = p_resource->get_class().to_snake_case(); existing = "new_" + resource_name_snake_case + "." + preferred.front()->get().to_lower(); } file->set_current_path(existing); @@ -1393,7 +1413,7 @@ void EditorNode::_get_scene_metadata(const String &p_file) { return; } - String path = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg"); + String path = EditorPaths::get_singleton()->get_project_settings_dir().path_join(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg"); Ref<ConfigFile> cf; cf.instantiate(); @@ -1425,7 +1445,7 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) { return; } - String path = EditorPaths::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg"); + String path = EditorPaths::get_singleton()->get_project_settings_dir().path_join(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg"); Ref<ConfigFile> cf; cf.instantiate(); @@ -1621,7 +1641,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { // Save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5. 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); + cache_base = temp_path.path_join("resthumb-" + cache_base); // Does not have it, try to load a cached thumbnail. String file = cache_base + ".png"; @@ -2402,6 +2422,16 @@ void EditorNode::_edit_current(bool p_skip_foreign) { InspectorDock::get_singleton()->update(current_obj); } +void EditorNode::_write_movie_toggled(bool p_enabled) { + if (p_enabled) { + launch_pad->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("LaunchPadMovieMode"), SNAME("EditorStyles"))); + write_movie_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("MovieWriterButtonPressed"), SNAME("EditorStyles"))); + } else { + launch_pad->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("LaunchPadNormal"), SNAME("EditorStyles"))); + write_movie_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("MovieWriterButtonNormal"), SNAME("EditorStyles"))); + } +} + void EditorNode::_run(bool p_current, const String &p_custom) { if (editor_run.get_status() == EditorRun::STATUS_PLAY) { play_button->set_pressed(!_playing_edited); @@ -2730,10 +2760,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { // Use casing of the root node. break; case SCENE_NAME_CASING_PASCAL_CASE: { - root_name = root_name.capitalize().replace(" ", ""); + root_name = root_name.to_pascal_case(); } break; case SCENE_NAME_CASING_SNAKE_CASE: - root_name = root_name.capitalize().replace(" ", "").replace("-", "_").camelcase_to_underscore(); + root_name = root_name.replace("-", "_").to_snake_case(); break; } file->set_current_path(root_name + "." + extensions.front()->get().to_lower()); @@ -2908,7 +2938,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { OS::get_singleton()->shell_open(String("file://") + OS::get_singleton()->get_user_data_dir()); } break; case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES: { - OS::get_singleton()->shell_open("file://" + ProjectSettings::get_singleton()->get_resource_path().plus_file("android")); + OS::get_singleton()->shell_open("file://" + ProjectSettings::get_singleton()->get_resource_path().path_join("android")); } break; case FILE_QUIT: case RUN_PROJECT_MANAGER: @@ -3065,14 +3095,14 @@ void EditorNode::_screenshot(bool p_use_utc) { } void EditorNode::_save_screenshot(NodePath p_path) { - Control *editor_main_control = EditorInterface::get_singleton()->get_editor_main_control(); - ERR_FAIL_COND_MSG(!editor_main_control, "Cannot get editor main control."); - Viewport *viewport = editor_main_control->get_viewport(); - ERR_FAIL_COND_MSG(!viewport, "Cannot get editor main control viewport."); + Control *editor_main_screen = EditorInterface::get_singleton()->get_editor_main_screen(); + ERR_FAIL_COND_MSG(!editor_main_screen, "Cannot get the editor main screen control."); + Viewport *viewport = editor_main_screen->get_viewport(); + ERR_FAIL_COND_MSG(!viewport, "Cannot get a viewport from the editor main screen."); Ref<ViewportTexture> texture = viewport->get_texture(); - ERR_FAIL_COND_MSG(texture.is_null(), "Cannot get editor main control viewport texture."); + ERR_FAIL_COND_MSG(texture.is_null(), "Cannot get a viewport texture from the editor main screen."); Ref<Image> img = texture->get_image(); - ERR_FAIL_COND_MSG(img.is_null(), "Cannot get editor main control viewport texture image."); + ERR_FAIL_COND_MSG(img.is_null(), "Cannot get an image from a viewport texture of the editor main screen."); Error error = img->save_png(p_path); ERR_FAIL_COND_MSG(error != OK, "Cannot save screenshot to file '" + p_path + "'."); } @@ -3256,8 +3286,8 @@ void EditorNode::_update_file_menu_closed() { file_menu->set_item_disabled(file_menu->get_item_index(FILE_OPEN_PREV), false); } -Control *EditorNode::get_main_control() { - return main_control; +VBoxContainer *EditorNode::get_main_screen_control() { + return main_screen_vbox; } void EditorNode::_editor_select(int p_which) { @@ -3445,7 +3475,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, // Only try to load the script if it has a name. Else, the plugin has no init script. if (script_path.length() > 0) { - script_path = addon_path.get_base_dir().plus_file(script_path); + script_path = addon_path.get_base_dir().path_join(script_path); script = ResourceLoader::load(script_path); if (script.is_null()) { @@ -4078,6 +4108,7 @@ void EditorNode::register_editor_types() { GDREGISTER_CLASS(EditorSyntaxHighlighter); GDREGISTER_ABSTRACT_CLASS(EditorInterface); GDREGISTER_CLASS(EditorExportPlugin); + GDREGISTER_ABSTRACT_CLASS(EditorExportPlatform); GDREGISTER_CLASS(EditorResourceConversionPlugin); GDREGISTER_CLASS(EditorSceneFormatImporter); GDREGISTER_CLASS(EditorScenePostImportPlugin); @@ -4304,16 +4335,8 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p } } - const HashMap<String, Vector<EditorData::CustomType>> &p_map = EditorNode::get_editor_data().get_custom_types(); - for (const KeyValue<String, Vector<EditorData::CustomType>> &E : p_map) { - 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; - } - } - } + if (const EditorData::CustomType *ctype = EditorNode::get_editor_data().get_custom_type_by_name(p_class)) { + return ctype->icon; } if (gui_base->has_theme_icon(p_class, SNAME("EditorIcons"))) { @@ -4563,7 +4586,7 @@ void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) { } if (nrect != dock_select_rect_over_idx) { - dock_select->update(); + dock_select->queue_redraw(); dock_select_rect_over_idx = nrect; } @@ -4589,7 +4612,7 @@ void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) { dock_popup_selected_idx = nrect; dock_slot[nrect]->set_current_tab(dock_slot[nrect]->get_tab_count() - 1); dock_slot[nrect]->show(); - dock_select->update(); + dock_select->queue_redraw(); _update_dock_containers(); @@ -4601,7 +4624,7 @@ void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) { void EditorNode::_dock_popup_exit() { dock_select_rect_over_idx = -1; - dock_select->update(); + dock_select->queue_redraw(); } void EditorNode::_dock_pre_popup(int p_which) { @@ -4619,7 +4642,7 @@ void EditorNode::_dock_move_left() { } dock_slot[dock_popup_selected_idx]->move_child(current, prev->get_index()); dock_slot[dock_popup_selected_idx]->set_current_tab(dock_slot[dock_popup_selected_idx]->get_current_tab() - 1); - dock_select->update(); + dock_select->queue_redraw(); _edit_current(); _save_docks(); } @@ -4632,7 +4655,7 @@ void EditorNode::_dock_move_right() { } dock_slot[dock_popup_selected_idx]->move_child(next, current->get_index()); dock_slot[dock_popup_selected_idx]->set_current_tab(dock_slot[dock_popup_selected_idx]->get_current_tab() + 1); - dock_select->update(); + dock_select->queue_redraw(); _edit_current(); _save_docks(); } @@ -4730,13 +4753,13 @@ void EditorNode::_save_docks() { Ref<ConfigFile> config; config.instantiate(); // Load and amend existing config if it exists. - config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg")); _save_docks_to_config(config, "docks"); _save_open_scenes_to_config(config, "EditorNode"); editor_data.get_plugin_window_layout(config); - config->save(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + config->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg")); } void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) { @@ -4800,7 +4823,7 @@ void EditorNode::_dock_split_dragged(int ofs) { void EditorNode::_load_docks() { Ref<ConfigFile> config; config.instantiate(); - Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg")); if (err != OK) { // No config. if (overridden_default_layout >= 0) { @@ -5033,7 +5056,7 @@ bool EditorNode::has_scenes_in_session() { } Ref<ConfigFile> config; config.instantiate(); - Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); + Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg")); if (err != OK) { return false; } @@ -5441,7 +5464,7 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { // This is the debug panel which uses tabs, so the top section should be smaller. bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), SNAME("EditorStyles"))); } else { - bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), SNAME("EditorStyles"))); } center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE); center_split->set_collapsed(false); @@ -5451,7 +5474,7 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { bottom_panel_raise->show(); } else { - bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), SNAME("EditorStyles"))); bottom_panel_items[p_idx].button->set_pressed(false); bottom_panel_items[p_idx].control->set_visible(false); center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN); @@ -5685,7 +5708,7 @@ void EditorNode::_add_dropped_files_recursive(const Vector<String> &p_files, Str for (int i = 0; i < p_files.size(); i++) { String from = p_files[i]; - String to = to_path.plus_file(from.get_file()); + String to = to_path.path_join(from.get_file()); if (dir->dir_exists(from)) { Vector<String> sub_files; @@ -5700,7 +5723,7 @@ void EditorNode::_add_dropped_files_recursive(const Vector<String> &p_files, Str continue; } - sub_files.push_back(from.plus_file(next_file)); + sub_files.push_back(from.path_join(next_file)); next_file = sub_dir->get_next(); } @@ -6487,12 +6510,13 @@ EditorNode::EditorNode() { tab_preview->set_position(Point2(2, 2) * EDSCALE); tab_preview_panel->add_child(tab_preview); + tabbar_panel = memnew(PanelContainer); + tabbar_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("tabbar_background"), SNAME("TabContainer"))); + srt->add_child(tabbar_panel); tabbar_container = memnew(HBoxContainer); - srt->add_child(tabbar_container); + tabbar_panel->add_child(tabbar_container); scene_tabs = memnew(TabBar); - scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox(SNAME("SceneTabFG"), SNAME("EditorStyles"))); - scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox(SNAME("SceneTabBG"), SNAME("EditorStyles"))); scene_tabs->set_select_with_rmb(true); scene_tabs->add_tab("unsaved"); scene_tabs->set_tab_close_display_policy((TabBar::CloseButtonDisplayPolicy)EDITOR_GET("interface/scene_tabs/display_close_button").operator int()); @@ -6551,10 +6575,11 @@ EditorNode::EditorNode() { scene_root->set_disable_input(true); scene_root->set_as_audio_listener_2d(true); - main_control = memnew(VBoxContainer); - main_control->set_v_size_flags(Control::SIZE_EXPAND_FILL); - main_control->add_theme_constant_override("separation", 0); - scene_root_parent->add_child(main_control); + main_screen_vbox = memnew(VBoxContainer); + main_screen_vbox->set_name("MainScreen"); + main_screen_vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL); + main_screen_vbox->add_theme_constant_override("separation", 0); + scene_root_parent->add_child(main_screen_vbox); bool global_menu = !bool(EDITOR_GET("interface/editor/use_embedded_menu")) && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU); bool can_expand = bool(EDITOR_GET("interface/editor/expand_to_title")) && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_EXTEND_TO_TITLE); @@ -6706,8 +6731,7 @@ EditorNode::EditorNode() { project_menu->add_child(vcs_actions_menu); project_menu->add_submenu_item(TTR("Version Control"), "Version Control"); vcs_actions_menu->add_item(TTR("Create Version Control Metadata"), RUN_VCS_METADATA); - 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); + vcs_actions_menu->add_item(TTR("Version Control Settings"), RUN_VCS_SETTINGS); project_menu->add_separator(); project_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/export", TTR("Export..."), Key::NONE, TTR("Export")), FILE_EXPORT_PROJECT); @@ -6822,12 +6846,16 @@ EditorNode::EditorNode() { right_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); menu_hb->add_child(right_spacer); - HBoxContainer *play_hb = memnew(HBoxContainer); - menu_hb->add_child(play_hb); + launch_pad = memnew(PanelContainer); + launch_pad->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("LaunchPadNormal"), SNAME("EditorStyles"))); + menu_hb->add_child(launch_pad); + + HBoxContainer *launch_pad_hb = memnew(HBoxContainer); + launch_pad->add_child(launch_pad_hb); play_button = memnew(Button); play_button->set_flat(true); - play_hb->add_child(play_button); + launch_pad_hb->add_child(play_button); play_button->set_toggle_mode(true); play_button->set_focus_mode(Control::FOCUS_NONE); play_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY)); @@ -6843,7 +6871,7 @@ EditorNode::EditorNode() { pause_button->set_focus_mode(Control::FOCUS_NONE); pause_button->set_tooltip_text(TTR("Pause the scene execution for debugging.")); pause_button->set_disabled(true); - play_hb->add_child(pause_button); + launch_pad_hb->add_child(pause_button); ED_SHORTCUT("editor/pause_scene", TTR("Pause Scene"), Key::F7); ED_SHORTCUT_OVERRIDE("editor/pause_scene", "macos", KeyModifierMask::CMD | KeyModifierMask::CTRL | Key::Y); @@ -6851,7 +6879,7 @@ EditorNode::EditorNode() { stop_button = memnew(Button); stop_button->set_flat(true); - play_hb->add_child(stop_button); + launch_pad_hb->add_child(stop_button); stop_button->set_focus_mode(Control::FOCUS_NONE); stop_button->set_icon(gui_base->get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"))); stop_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_STOP)); @@ -6863,12 +6891,12 @@ EditorNode::EditorNode() { stop_button->set_shortcut(ED_GET_SHORTCUT("editor/stop")); run_native = memnew(EditorRunNative); - play_hb->add_child(run_native); + launch_pad_hb->add_child(run_native); run_native->connect("native_run", callable_mp(this, &EditorNode::_run_native)); play_scene_button = memnew(Button); play_scene_button->set_flat(true); - play_hb->add_child(play_scene_button); + launch_pad_hb->add_child(play_scene_button); play_scene_button->set_toggle_mode(true); play_scene_button->set_focus_mode(Control::FOCUS_NONE); play_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY_SCENE)); @@ -6879,7 +6907,7 @@ EditorNode::EditorNode() { play_custom_scene_button = memnew(Button); play_custom_scene_button->set_flat(true); - play_hb->add_child(play_custom_scene_button); + launch_pad_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); play_custom_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY_CUSTOM_SCENE)); @@ -6890,18 +6918,23 @@ EditorNode::EditorNode() { ED_SHORTCUT_OVERRIDE("editor/play_custom_scene", "macos", KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::R); play_custom_scene_button->set_shortcut(ED_GET_SHORTCUT("editor/play_custom_scene")); + write_movie_panel = memnew(PanelContainer); + write_movie_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("MovieWriterButtonNormal"), SNAME("EditorStyles"))); + launch_pad_hb->add_child(write_movie_panel); + write_movie_button = memnew(Button); write_movie_button->set_flat(true); write_movie_button->set_toggle_mode(true); - play_hb->add_child(write_movie_button); + write_movie_panel->add_child(write_movie_button); write_movie_button->set_pressed(false); write_movie_button->set_icon(gui_base->get_theme_icon(SNAME("MainMovieWrite"), SNAME("EditorIcons"))); write_movie_button->set_focus_mode(Control::FOCUS_NONE); + write_movie_button->connect("toggled", callable_mp(this, &EditorNode::_write_movie_toggled)); write_movie_button->set_tooltip_text(TTR("Enable Movie Maker mode.\nThe project will run at stable FPS and the visual and audio output will be recorded to a video file.")); // This button behaves differently, so color it as such. write_movie_button->add_theme_color_override("icon_normal_color", Color(1, 1, 1, 0.7)); - write_movie_button->add_theme_color_override("icon_pressed_color", gui_base->get_theme_color(SNAME("error_color"), SNAME("Editor"))); + write_movie_button->add_theme_color_override("icon_pressed_color", Color(0, 0, 0, 0.84)); write_movie_button->add_theme_color_override("icon_hover_color", Color(1, 1, 1, 0.9)); HBoxContainer *right_menu_hb = memnew(HBoxContainer); @@ -7048,7 +7081,7 @@ EditorNode::EditorNode() { // Bottom panels. bottom_panel = memnew(PanelContainer); - bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); + bottom_panel->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("BottomPanel"), SNAME("EditorStyles"))); center_split->add_child(bottom_panel); center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN); @@ -7305,6 +7338,7 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(GPUParticles2DEditorPlugin)); add_editor_plugin(memnew(LightOccluder2DEditorPlugin)); add_editor_plugin(memnew(Line2DEditorPlugin)); + add_editor_plugin(memnew(NavigationLink2DEditorPlugin)); add_editor_plugin(memnew(NavigationPolygonEditorPlugin)); add_editor_plugin(memnew(Path2DEditorPlugin)); add_editor_plugin(memnew(Polygon2DEditorPlugin)); @@ -7378,11 +7412,6 @@ EditorNode::EditorNode() { editor_plugins_force_over = memnew(EditorPluginList); editor_plugins_force_input_forwarding = memnew(EditorPluginList); - Ref<EditorExportTextSceneToBinaryPlugin> export_text_to_binary_plugin; - export_text_to_binary_plugin.instantiate(); - - EditorExport::get_singleton()->add_export_plugin(export_text_to_binary_plugin); - Ref<GDExtensionExportPlugin> gdextension_export_plugin; gdextension_export_plugin.instantiate(); @@ -7486,9 +7515,9 @@ EditorNode::EditorNode() { screenshot_timer->set_owner(get_owner()); // Adjust spacers to center 2D / 3D / Script buttons. - int max_w = MAX(play_hb->get_minimum_size().x + right_menu_hb->get_minimum_size().x, main_menu->get_minimum_size().x); + int max_w = MAX(launch_pad_hb->get_minimum_size().x + right_menu_hb->get_minimum_size().x, main_menu->get_minimum_size().x); left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu->get_minimum_size().x), 0)); - right_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - play_hb->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); + right_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - launch_pad_hb->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); // Extend menu bar to window title. if (can_expand) { |