From 8a74d8438f5dee92927d953a7954ad3c3022cbd9 Mon Sep 17 00:00:00 2001 From: Yuri Sizov Date: Wed, 12 Apr 2023 21:02:28 +0200 Subject: [PATCH] Extract editor run toolbar into its own component - Simplify and update its logic. - Simplify EditorScript. - Improve EditorNode and other relevant includes. - Fix scene-based path in the movie writer when reloading a scene. --- doc/classes/EditorScript.xml | 4 +- .../debug_adapter/debug_adapter_parser.cpp | 17 +- .../debug_adapter/debug_adapter_protocol.cpp | 6 +- editor/debugger/editor_debugger_node.cpp | 16 +- editor/editor_data.cpp | 10 + editor/editor_data.h | 3 + editor/editor_interface.cpp | 17 +- editor/editor_node.cpp | 498 ++++-------------- editor/editor_node.h | 59 +-- editor/editor_plugin.cpp | 4 +- editor/editor_plugin_settings.cpp | 1 + editor/editor_run.h | 1 + editor/editor_run_native.cpp | 7 +- editor/editor_run_native.h | 6 +- ...ditor_run_script.cpp => editor_script.cpp} | 33 +- .../{editor_run_script.h => editor_script.h} | 21 +- editor/editor_settings.h | 3 +- editor/export/editor_export_platform.cpp | 1 + editor/gui/editor_run_bar.cpp | 442 ++++++++++++++++ editor/gui/editor_run_bar.h | 115 ++++ editor/plugins/canvas_item_editor_plugin.cpp | 5 +- editor/plugins/curve_editor_plugin.cpp | 1 + editor/plugins/curve_editor_plugin.h | 2 + editor/plugins/material_editor_plugin.cpp | 1 + editor/plugins/node_3d_editor_plugin.cpp | 5 +- editor/plugins/script_editor_plugin.cpp | 11 +- editor/plugins/script_text_editor.cpp | 1 + editor/project_settings_editor.cpp | 1 + editor/register_editor_types.cpp | 6 +- .../editor_scene_exporter_gltf_plugin.cpp | 1 + modules/mono/editor/editor_internal_calls.cpp | 5 +- platform/ios/export/export_plugin.cpp | 1 + platform/linuxbsd/export/export_plugin.cpp | 1 + platform/uwp/export/export.cpp | 1 + platform/web/export/export.cpp | 1 + platform/web/export/export_plugin.cpp | 1 + platform/windows/export/export_plugin.cpp | 1 + 37 files changed, 771 insertions(+), 538 deletions(-) rename editor/{editor_run_script.cpp => editor_script.cpp} (87%) rename editor/{editor_run_script.h => editor_script.h} (88%) create mode 100644 editor/gui/editor_run_bar.cpp create mode 100644 editor/gui/editor_run_bar.h diff --git a/doc/classes/EditorScript.xml b/doc/classes/EditorScript.xml index ecaa21efb3c4..d77d11857b56 100644 --- a/doc/classes/EditorScript.xml +++ b/doc/classes/EditorScript.xml @@ -48,13 +48,13 @@ [b]Warning:[/b] The implementation of this method is currently disabled. - + Returns the [EditorInterface] singleton instance. - + Returns the Editor's currently active scene. diff --git a/editor/debugger/debug_adapter/debug_adapter_parser.cpp b/editor/debugger/debug_adapter/debug_adapter_parser.cpp index fc806ded5ecd..e3686a0217d3 100644 --- a/editor/debugger/debug_adapter/debug_adapter_parser.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_parser.cpp @@ -32,9 +32,8 @@ #include "editor/debugger/editor_debugger_node.h" #include "editor/debugger/script_editor_debugger.h" -#include "editor/editor_node.h" -#include "editor/editor_run_native.h" #include "editor/export/editor_export_platform.h" +#include "editor/gui/editor_run_bar.h" #include "editor/plugins/script_editor_plugin.h" void DebugAdapterParser::_bind_methods() { @@ -162,7 +161,7 @@ Dictionary DebugAdapterParser::req_initialize(const Dictionary &p_params) const Dictionary DebugAdapterParser::req_disconnect(const Dictionary &p_params) const { if (!DebugAdapterProtocol::get_singleton()->get_current_peer()->attached) { - EditorNode::get_singleton()->run_stop(); + EditorRunBar::get_singleton()->stop_playing(); } return prepare_success_response(p_params); @@ -188,7 +187,7 @@ Dictionary DebugAdapterParser::req_launch(const Dictionary &p_params) const { String platform_string = args.get("platform", "host"); if (platform_string == "host") { - EditorNode::get_singleton()->run_play(); + EditorRunBar::get_singleton()->play_main_scene(); } else { int device = args.get("device", -1); int idx = -1; @@ -212,8 +211,8 @@ Dictionary DebugAdapterParser::req_launch(const Dictionary &p_params) const { return prepare_error_response(p_params, DAP::ErrorType::UNKNOWN_PLATFORM); } - EditorNode *editor = EditorNode::get_singleton(); - Error err = platform_string == "android" ? editor->run_play_native(device * 10000 + idx) : editor->run_play_native(idx); + EditorRunBar *run_bar = EditorRunBar::get_singleton(); + Error err = platform_string == "android" ? run_bar->start_native_device(device * 10000 + idx) : run_bar->start_native_device(idx); if (err) { if (err == ERR_INVALID_PARAMETER && platform_string == "android") { return prepare_error_response(p_params, DAP::ErrorType::MISSING_DEVICE); @@ -257,13 +256,13 @@ Dictionary DebugAdapterParser::req_restart(const Dictionary &p_params) const { } Dictionary DebugAdapterParser::req_terminate(const Dictionary &p_params) const { - EditorNode::get_singleton()->run_stop(); + EditorRunBar::get_singleton()->stop_playing(); return prepare_success_response(p_params); } Dictionary DebugAdapterParser::req_pause(const Dictionary &p_params) const { - EditorNode::get_singleton()->get_pause_button()->set_pressed(true); + EditorRunBar::get_singleton()->get_pause_button()->set_pressed(true); EditorDebuggerNode::get_singleton()->_paused(); DebugAdapterProtocol::get_singleton()->notify_stopped_paused(); @@ -272,7 +271,7 @@ Dictionary DebugAdapterParser::req_pause(const Dictionary &p_params) const { } Dictionary DebugAdapterParser::req_continue(const Dictionary &p_params) const { - EditorNode::get_singleton()->get_pause_button()->set_pressed(false); + EditorRunBar::get_singleton()->get_pause_button()->set_pressed(false); EditorDebuggerNode::get_singleton()->_paused(); DebugAdapterProtocol::get_singleton()->notify_continued(); diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp index f85163cd6ae2..26fb73570e4d 100644 --- a/editor/debugger/debug_adapter/debug_adapter_protocol.cpp +++ b/editor/debugger/debug_adapter/debug_adapter_protocol.cpp @@ -38,6 +38,7 @@ #include "editor/editor_log.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" +#include "editor/gui/editor_run_bar.h" DebugAdapterProtocol *DebugAdapterProtocol::singleton = nullptr; @@ -812,7 +813,7 @@ Array DebugAdapterProtocol::update_breakpoints(const String &p_path, const Array } void DebugAdapterProtocol::on_debug_paused() { - if (EditorNode::get_singleton()->get_pause_button()->is_pressed()) { + if (EditorRunBar::get_singleton()->get_pause_button()->is_pressed()) { notify_stopped_paused(); } else { notify_continued(); @@ -1017,8 +1018,7 @@ DebugAdapterProtocol::DebugAdapterProtocol() { reset_ids(); - EditorNode *node = EditorNode::get_singleton(); - node->get_pause_button()->connect("pressed", callable_mp(this, &DebugAdapterProtocol::on_debug_paused)); + EditorRunBar::get_singleton()->get_pause_button()->connect("pressed", callable_mp(this, &DebugAdapterProtocol::on_debug_paused)); EditorDebuggerNode *debugger_node = EditorDebuggerNode::get_singleton(); debugger_node->connect("breakpoint_toggled", callable_mp(this, &DebugAdapterProtocol::on_debug_breakpoint_toggled)); diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp index a368cacf56ab..7083640b2477 100644 --- a/editor/debugger/editor_debugger_node.cpp +++ b/editor/debugger/editor_debugger_node.cpp @@ -37,6 +37,7 @@ #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/gui/editor_run_bar.h" #include "editor/inspector_dock.h" #include "editor/plugins/editor_debugger_plugin.h" #include "editor/plugins/script_editor_plugin.h" @@ -87,8 +88,7 @@ EditorDebuggerNode::EditorDebuggerNode() { remote_scene_tree_timeout = EDITOR_DEF("debugger/remote_scene_tree_refresh_interval", 1.0); inspect_edited_object_timeout = EDITOR_DEF("debugger/remote_inspect_refresh_interval", 0.2); - EditorNode *editor = EditorNode::get_singleton(); - editor->get_pause_button()->connect("pressed", callable_mp(this, &EditorDebuggerNode::_paused)); + EditorRunBar::get_singleton()->get_pause_button()->connect("pressed", callable_mp(this, &EditorDebuggerNode::_paused)); } ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() { @@ -260,7 +260,7 @@ void EditorDebuggerNode::stop(bool p_force) { server->stop(); EditorNode::get_log()->add_message("--- Debugging process stopped ---", EditorLog::MSG_TYPE_EDITOR); - if (EditorNode::get_singleton()->is_movie_maker_enabled()) { + if (EditorRunBar::get_singleton()->is_movie_maker_enabled()) { // Request attention in case the user was doing something else when movie recording is finished. DisplayServer::get_singleton()->window_request_attention(); } @@ -344,7 +344,7 @@ void EditorDebuggerNode::_notification(int p_what) { } } - EditorNode::get_singleton()->get_pause_button()->set_disabled(false); + EditorRunBar::get_singleton()->get_pause_button()->set_disabled(false); // Switch to remote tree view if so desired. auto_switch_remote_scene_tree = (bool)EDITOR_GET("debugger/auto_switch_to_remote_scene_tree"); if (auto_switch_remote_scene_tree) { @@ -413,8 +413,8 @@ void EditorDebuggerNode::_debugger_stopped(int p_id) { } }); if (!found) { - EditorNode::get_singleton()->get_pause_button()->set_pressed(false); - EditorNode::get_singleton()->get_pause_button()->set_disabled(true); + EditorRunBar::get_singleton()->get_pause_button()->set_pressed(false); + EditorRunBar::get_singleton()->get_pause_button()->set_disabled(true); SceneTreeDock::get_singleton()->hide_remote_tree(); SceneTreeDock::get_singleton()->hide_tab_buttons(); EditorNode::get_singleton()->notify_all_debug_sessions_exited(); @@ -509,7 +509,7 @@ void EditorDebuggerNode::_update_debug_options() { } void EditorDebuggerNode::_paused() { - const bool paused = EditorNode::get_singleton()->get_pause_button()->is_pressed(); + const bool paused = EditorRunBar::get_singleton()->get_pause_button()->is_pressed(); _for_all(tabs, [&](ScriptEditorDebugger *dbg) { if (paused && !dbg->is_breaked()) { dbg->debug_break(); @@ -527,7 +527,7 @@ void EditorDebuggerNode::_breaked(bool p_breaked, bool p_can_debug, String p_mes tabs->set_current_tab(p_debugger); } _break_state_changed(); - EditorNode::get_singleton()->get_pause_button()->set_pressed(p_breaked); + EditorRunBar::get_singleton()->get_pause_button()->set_pressed(p_breaked); emit_signal(SNAME("breaked"), p_breaked, p_can_debug); } diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 1421db42ec7d..1f9d7541855a 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -713,6 +713,16 @@ int EditorData::get_edited_scene() const { return current_edited_scene; } +int EditorData::get_edited_scene_from_path(const String &p_path) const { + for (int i = 0; i < edited_scene.size(); i++) { + if (edited_scene[i].path == p_path) { + return i; + } + } + + return -1; +} + void EditorData::set_edited_scene(int p_idx) { ERR_FAIL_INDEX(p_idx, edited_scene.size()); current_edited_scene = p_idx; diff --git a/editor/editor_data.h b/editor/editor_data.h index 370963074c53..d4a2f534cdbb 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -196,9 +196,11 @@ public: void set_edited_scene(int p_idx); void set_edited_scene_root(Node *p_root); int get_edited_scene() const; + int get_edited_scene_from_path(const String &p_path) const; Node *get_edited_scene_root(int p_idx = -1); int get_edited_scene_count() const; Vector get_edited_scenes() const; + String get_scene_title(int p_idx, bool p_always_strip_extension = false) const; String get_scene_path(int p_idx) const; String get_scene_type(int p_idx) const; @@ -211,6 +213,7 @@ public: NodePath get_edited_scene_live_edit_root(); bool check_and_update_scene(int p_idx); void move_edited_scene_to_index(int p_idx); + bool call_build(); void set_scene_as_saved(int p_idx); diff --git a/editor/editor_interface.cpp b/editor/editor_interface.cpp index 99803fd82dab..167a5a3dba3a 100644 --- a/editor/editor_interface.cpp +++ b/editor/editor_interface.cpp @@ -37,6 +37,7 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/filesystem_dock.h" +#include "editor/gui/editor_run_bar.h" #include "editor/inspector_dock.h" #include "main/main.h" #include "scene/gui/box_container.h" @@ -317,35 +318,35 @@ void EditorInterface::save_scene_as(const String &p_scene, bool p_with_preview) // Scene playback. void EditorInterface::play_main_scene() { - EditorNode::get_singleton()->run_play(); + EditorRunBar::get_singleton()->play_main_scene(); } void EditorInterface::play_current_scene() { - EditorNode::get_singleton()->run_play_current(); + EditorRunBar::get_singleton()->play_current_scene(); } void EditorInterface::play_custom_scene(const String &scene_path) { - EditorNode::get_singleton()->run_play_custom(scene_path); + EditorRunBar::get_singleton()->play_custom_scene(scene_path); } void EditorInterface::stop_playing_scene() { - EditorNode::get_singleton()->run_stop(); + EditorRunBar::get_singleton()->stop_playing(); } bool EditorInterface::is_playing_scene() const { - return EditorNode::get_singleton()->is_run_playing(); + return EditorRunBar::get_singleton()->is_playing(); } String EditorInterface::get_playing_scene() const { - return EditorNode::get_singleton()->get_run_playing_scene(); + return EditorRunBar::get_singleton()->get_playing_scene(); } void EditorInterface::set_movie_maker_enabled(bool p_enabled) { - EditorNode::get_singleton()->set_movie_maker_enabled(p_enabled); + EditorRunBar::get_singleton()->set_movie_maker_enabled(p_enabled); } bool EditorInterface::is_movie_maker_enabled() const { - return EditorNode::get_singleton()->is_movie_maker_enabled(); + return EditorRunBar::get_singleton()->is_movie_maker_enabled(); } // Base. diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index f2f12857999d..fc1ab9ef18c8 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -53,6 +53,8 @@ #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" #include "scene/gui/panel_container.h" +#include "scene/gui/popup.h" +#include "scene/gui/rich_text_label.h" #include "scene/gui/split_container.h" #include "scene/gui/tab_bar.h" #include "scene/gui/tab_container.h" @@ -99,6 +101,7 @@ #include "editor/fbx_importer_manager.h" #include "editor/filesystem_dock.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/gui/editor_run_bar.h" #include "editor/gui/editor_title_bar.h" #include "editor/gui/editor_toaster.h" #include "editor/history_dock.h" @@ -802,20 +805,6 @@ 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"))); - pause_button->set_icon(gui_base->get_theme_icon(SNAME("Pause"), SNAME("EditorIcons"))); - stop_button->set_icon(gui_base->get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"))); - prev_scene->set_icon(gui_base->get_theme_icon(SNAME("PrevScene"), SNAME("EditorIcons"))); distraction_free->set_icon(gui_base->get_theme_icon(SNAME("DistractionFree"), SNAME("EditorIcons"))); scene_tab_add->set_icon(gui_base->get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); @@ -1194,7 +1183,7 @@ void EditorNode::_vp_resized() { } void EditorNode::_titlebar_resized() { - DisplayServer::get_singleton()->window_set_window_buttons_offset(Vector2i(menu_hb->get_global_position().y + menu_hb->get_size().y / 2, menu_hb->get_global_position().y + menu_hb->get_size().y / 2), DisplayServer::MAIN_WINDOW_ID); + DisplayServer::get_singleton()->window_set_window_buttons_offset(Vector2i(title_bar->get_global_position().y + title_bar->get_size().y / 2, title_bar->get_global_position().y + title_bar->get_size().y / 2), DisplayServer::MAIN_WINDOW_ID); const Vector3i &margin = DisplayServer::get_singleton()->window_get_safe_title_margins(DisplayServer::MAIN_WINDOW_ID); if (left_menu_spacer) { int w = (gui_base->is_layout_rtl()) ? margin.y : margin.x; @@ -1204,8 +1193,8 @@ void EditorNode::_titlebar_resized() { int w = (gui_base->is_layout_rtl()) ? margin.x : margin.y; right_menu_spacer->set_custom_minimum_size(Size2(w, 0)); } - if (menu_hb) { - menu_hb->set_custom_minimum_size(Size2(0, margin.z - menu_hb->get_global_position().y)); + if (title_bar) { + title_bar->set_custom_minimum_size(Size2(0, margin.z - title_bar->get_global_position().y)); } } @@ -1814,7 +1803,7 @@ void EditorNode::_save_scene(String p_file, int idx) { editor_data.apply_changes_in_editors(); List> anim_backups; _reset_animation_players(scene, &anim_backups); - _save_default_environment(); + save_default_environment(); _set_scene_metadata(p_file, idx); @@ -1876,7 +1865,7 @@ void EditorNode::_save_scene(String p_file, int idx) { } void EditorNode::save_all_scenes() { - _menu_option_confirm(RUN_STOP, true); + project_run_bar->stop_playing(); _save_all_scenes(); } @@ -1890,11 +1879,33 @@ void EditorNode::save_scene_list(Vector p_scene_filenames) { } } +void EditorNode::save_before_run() { + current_menu_option = FILE_SAVE_AND_RUN; + _menu_option_confirm(FILE_SAVE_AS_SCENE, true); + file->set_title(TTR("Save scene before running...")); +} + +void EditorNode::try_autosave() { + if (!bool(EDITOR_GET("run/auto_save/save_before_running"))) { + return; + } + + if (unsaved_cache) { + Node *scene = editor_data.get_edited_scene_root(); + + if (scene && !scene->get_scene_file_path().is_empty()) { // Only autosave if there is a scene and if it has a path. + _save_scene_with_preview(scene->get_scene_file_path()); + } + } + _menu_option(FILE_SAVE_ALL_SCENES); + editor_data.save_editor_external_data(); +} + void EditorNode::restart_editor() { exiting = true; - if (editor_run.get_status() != EditorRun::STATUS_STOP) { - editor_run.stop(); + if (project_run_bar->is_playing()) { + project_run_bar->stop_playing(); } String to_reopen; @@ -1942,7 +1953,7 @@ void EditorNode::_save_all_scenes() { if (!all_saved) { show_warning(TTR("Could not save one or more scenes!"), TTR("Save All Scenes")); } - _save_default_environment(); + save_default_environment(); } void EditorNode::_mark_unsaved_scenes() { @@ -1982,11 +1993,7 @@ void EditorNode::_dialog_action(String p_file) { ProjectSettings::get_singleton()->save(); // TODO: Would be nice to show the project manager opened with the highlighted field. - if ((bool)pick_main_scene->get_meta("from_native", false)) { - run_native->resume_run_native(); - } else { - _run(false, ""); // Automatically run the project. - } + project_run_bar->play_main_scene((bool)pick_main_scene->get_meta("from_native", false)); } break; case FILE_CLOSE: case SCENE_TAB_CLOSE: @@ -2007,7 +2014,7 @@ void EditorNode::_dialog_action(String p_file) { return; } - _save_default_environment(); + save_default_environment(); _save_scene_with_preview(p_file, scene_idx); _add_to_recent_scenes(p_file); save_layout(); @@ -2021,9 +2028,9 @@ void EditorNode::_dialog_action(String p_file) { case FILE_SAVE_AND_RUN: { if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { - _save_default_environment(); + save_default_environment(); _save_scene_with_preview(p_file); - _run(false, p_file); + project_run_bar->play_custom_scene(p_file); } } break; @@ -2032,13 +2039,9 @@ void EditorNode::_dialog_action(String p_file) { ProjectSettings::get_singleton()->save(); if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { - _save_default_environment(); + save_default_environment(); _save_scene_with_preview(p_file); - if ((bool)pick_main_scene->get_meta("from_native", false)) { - run_native->resume_run_native(); - } else { - _run(false, p_file); - } + project_run_bar->play_main_scene((bool)pick_main_scene->get_meta("from_native", false)); } } break; @@ -2250,7 +2253,7 @@ void EditorNode::push_item(Object *p_object, const String &p_property, bool p_in _edit_current(); } -void EditorNode::_save_default_environment() { +void EditorNode::save_default_environment() { Ref fallback = get_tree()->get_root()->get_world_3d()->get_fallback_environment(); if (fallback.is_valid() && fallback->get_path().is_resource_file()) { @@ -2496,157 +2499,6 @@ 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); - play_scene_button->set_pressed(_playing_edited); - return; - } - - play_button->set_pressed(false); - play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); - play_scene_button->set_pressed(false); - play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons"))); - play_custom_scene_button->set_pressed(false); - play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons"))); - - String write_movie_file; - if (write_movie_button->is_pressed()) { - if (p_current && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->has_meta("movie_file")) { - // If the scene file has a movie_file metadata set, use this as file. Quick workaround if you want to have multiple scenes that write to multiple movies. - write_movie_file = get_tree()->get_edited_scene_root()->get_meta("movie_file"); - } else { - write_movie_file = GLOBAL_GET("editor/movie_writer/movie_file"); - } - if (write_movie_file == String()) { - show_accept(TTR("Movie Maker mode is enabled, but no movie file path has been specified.\nA default movie file path can be specified in the project settings under the Editor > Movie Writer category.\nAlternatively, for running single scenes, a `movie_file` string metadata can be added to the root node,\nspecifying the path to a movie file that will be used when recording that scene."), TTR("OK")); - return; - } - } - - String run_filename; - - if ((p_current && p_custom.is_empty()) || (editor_data.get_edited_scene_root() && !p_custom.is_empty() && p_custom == editor_data.get_edited_scene_root()->get_scene_file_path())) { - Node *scene = editor_data.get_edited_scene_root(); - - if (!scene) { - show_accept(TTR("There is no defined scene to run."), TTR("OK")); - return; - } - - if (scene->get_scene_file_path().is_empty()) { - current_menu_option = FILE_SAVE_AND_RUN; - _menu_option_confirm(FILE_SAVE_AS_SCENE, true); - file->set_title(TTR("Save scene before running...")); - return; - } - - run_filename = scene->get_scene_file_path(); - } else if (!p_custom.is_empty()) { - run_filename = p_custom; - } - - if (run_filename.is_empty()) { - // Evidently, run the scene. - if (!ensure_main_scene(false)) { - return; - } - run_filename = GLOBAL_DEF_BASIC("application/run/main_scene", ""); - } - - if (bool(EDITOR_GET("run/auto_save/save_before_running"))) { - if (unsaved_cache) { - Node *scene = editor_data.get_edited_scene_root(); - - if (scene && !scene->get_scene_file_path().is_empty()) { // Only autosave if there is a scene and if it has a path. - _save_scene_with_preview(scene->get_scene_file_path()); - } - } - _menu_option(FILE_SAVE_ALL_SCENES); - editor_data.save_editor_external_data(); - } - - if (!call_build()) { - return; - } - - if (bool(EDITOR_GET("run/output/always_clear_output_on_play"))) { - log->clear(); - } - - if (bool(EDITOR_GET("run/output/always_open_output_on_play"))) { - make_bottom_panel_item_visible(log); - } - - EditorDebuggerNode::get_singleton()->start(); - Error error = editor_run.run(run_filename, write_movie_file); - if (error != OK) { - EditorDebuggerNode::get_singleton()->stop(); - show_accept(TTR("Could not start subprocess(es)!"), TTR("OK")); - return; - } - - emit_signal(SNAME("play_pressed")); - if (p_current) { - run_current_filename = run_filename; - play_scene_button->set_pressed(true); - play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); - play_scene_button->set_tooltip_text(TTR("Reload the played scene.")); - } else if (!p_custom.is_empty()) { - run_custom_filename = p_custom; - play_custom_scene_button->set_pressed(true); - play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); - play_custom_scene_button->set_tooltip_text(TTR("Reload the played scene.")); - } else { - play_button->set_pressed(true); - play_button->set_icon(gui_base->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); - play_button->set_tooltip_text(TTR("Reload the played scene.")); - } - stop_button->set_disabled(false); - - _playing_edited = p_current; -} - -void EditorNode::_run_native(const Ref &p_preset) { - bool autosave = EDITOR_GET("run/auto_save/save_before_running"); - if (autosave) { - _menu_option_confirm(FILE_SAVE_ALL_SCENES, false); - } - if (run_native->is_deploy_debug_remote_enabled()) { - _menu_option_confirm(RUN_STOP, true); - - if (!call_build()) { - return; // Build failed. - } - - EditorDebuggerNode::get_singleton()->start(p_preset->get_platform()->get_debug_protocol()); - emit_signal(SNAME("play_pressed")); - editor_run.run_native_notify(); - } -} - -void EditorNode::_reset_play_buttons() { - play_button->set_pressed(false); - play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); - play_button->set_tooltip_text(TTR("Play the project.")); - play_scene_button->set_pressed(false); - play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons"))); - play_scene_button->set_tooltip_text(TTR("Play the edited scene.")); - play_custom_scene_button->set_pressed(false); - play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons"))); - play_custom_scene_button->set_tooltip_text(TTR("Play a custom scene.")); -} - void EditorNode::_android_build_source_selected(const String &p_file) { export_template_manager->install_android_template_from_file(p_file); } @@ -2813,6 +2665,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { _save_all_scenes(); } break; + case FILE_RUN_SCENE: { + project_run_bar->play_current_scene(); + } break; + case FILE_EXPORT_PROJECT: { project_export->popup_export(); } break; @@ -2916,45 +2772,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { EditorUndoRedoManager::get_singleton()->clear_history(false, editor_data.get_current_edited_scene_history_id()); scene_tabs->set_current_tab(cur_idx); - } break; - case RUN_PLAY: { - run_play(); - - } break; - case RUN_PLAY_CUSTOM_SCENE: { - if (run_custom_filename.is_empty() || editor_run.get_status() == EditorRun::STATUS_STOP) { - _menu_option_confirm(RUN_STOP, true); - quick_run->popup_dialog("PackedScene", true); - quick_run->set_title(TTR("Quick Run Scene...")); - play_custom_scene_button->set_pressed(false); - } else { - String last_custom_scene = run_custom_filename; // This is necessary to have a copy of the string. - run_play_custom(last_custom_scene); - } - - } break; - case RUN_STOP: { - if (editor_run.get_status() == EditorRun::STATUS_STOP) { - break; - } - - editor_run.stop(); - run_custom_filename.clear(); - run_current_filename.clear(); - stop_button->set_disabled(true); - _reset_play_buttons(); - - if (bool(EDITOR_GET("run/output/always_close_output_on_stop"))) { - for (int i = 0; i < bottom_panel_items.size(); i++) { - if (bottom_panel_items[i].control == log) { - _bottom_panel_switch(false, i); - break; - } - } - } - EditorDebuggerNode::get_singleton()->stop(); - emit_signal(SNAME("stop_pressed")); - } break; case FILE_SHOW_IN_FILESYSTEM: { @@ -2964,15 +2781,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } } break; - case RUN_PLAY_SCENE: { - if (run_current_filename.is_empty() || editor_run.get_status() == EditorRun::STATUS_STOP) { - run_play_current(); - } else { - String last_current_scene = run_current_filename; // This is necessary to have a copy of the string. - run_play_custom(last_current_scene); - } - - } break; case RUN_SETTINGS: { project_settings_editor->popup_project_settings(); } break; @@ -3296,12 +3104,12 @@ void EditorNode::_discard_changes(const String &p_str) { _proceed_closing_scene_tabs(); } break; case FILE_QUIT: { - _menu_option_confirm(RUN_STOP, true); + project_run_bar->stop_playing(); _exit_editor(EXIT_SUCCESS); } break; case RUN_PROJECT_MANAGER: { - _menu_option_confirm(RUN_STOP, true); + project_run_bar->stop_playing(); _exit_editor(EXIT_SUCCESS); String exec = OS::get_singleton()->get_executable_path(); @@ -3584,14 +3392,6 @@ bool EditorNode::is_addon_plugin_enabled(const String &p_addon) const { return addon_name_to_plugin.has("res://addons/" + p_addon + "/plugin.cfg"); } -void EditorNode::set_movie_maker_enabled(bool p_enabled) { - write_movie_button->set_pressed(p_enabled); -} - -bool EditorNode::is_movie_maker_enabled() const { - return write_movie_button->is_pressed(); -} - void EditorNode::_remove_edited_scene(bool p_change_tab) { int new_index = editor_data.get_edited_scene(); int old_index = new_index; @@ -4260,14 +4060,31 @@ void EditorNode::_quick_opened() { } } -void EditorNode::_quick_run() { - _run(false, quick_run->get_selected()); +void EditorNode::_project_run_started() { + if (bool(EDITOR_GET("run/output/always_clear_output_on_play"))) { + log->clear(); + } + + if (bool(EDITOR_GET("run/output/always_open_output_on_play"))) { + make_bottom_panel_item_visible(log); + } +} + +void EditorNode::_project_run_stopped() { + if (!bool(EDITOR_GET("run/output/always_close_output_on_stop"))) { + return; + } + + for (int i = 0; i < bottom_panel_items.size(); i++) { + if (bottom_panel_items[i].control == log) { + _bottom_panel_switch(false, i); + break; + } + } } void EditorNode::notify_all_debug_sessions_exited() { - _menu_option_confirm(RUN_STOP, false); - stop_button->set_pressed(false); - editor_run.stop(); + project_run_bar->stop_playing(); } void EditorNode::add_io_error(const String &p_error) { @@ -4305,13 +4122,12 @@ bool EditorNode::is_scene_in_use(const String &p_path) { return false; } +OS::ProcessID EditorNode::has_child_process(OS::ProcessID p_pid) const { + return project_run_bar->has_child_process(p_pid); +} + void EditorNode::stop_child_process(OS::ProcessID p_pid) { - if (has_child_process(p_pid)) { - editor_run.stop_child_process(p_pid); - if (!editor_run.get_child_process_count()) { // All children stopped. Closing. - _menu_option_confirm(RUN_STOP, false); - } - } + project_run_bar->stop_child_process(p_pid); } Ref