diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index 1fbb8368f4ae..4aa885e33138 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -46,7 +46,7 @@ String EditorRun::get_running_scene() const { return running_scene; } -Error EditorRun::run(const String &p_scene, const String &p_write_movie) { +Error EditorRun::run(const String &p_scene, const String &p_write_movie, List *p_run_args) { List args; for (const String &a : Main::get_forwardable_cli_arguments(Main::CLI_SCOPE_PROJECT)) { @@ -223,6 +223,12 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) { args.push_back(p_scene); } + if (p_run_args != nullptr) { + for (const String &run_arg : *p_run_args) { + args.push_back(run_arg); + } + } + String exec = OS::get_singleton()->get_executable_path(); int instance_count = RunInstancesDialog::get_singleton()->get_instance_count(); for (int i = 0; i < instance_count; i++) { diff --git a/editor/editor_run.h b/editor/editor_run.h index 387d15246b63..c2779942b239 100644 --- a/editor/editor_run.h +++ b/editor/editor_run.h @@ -55,7 +55,7 @@ class EditorRun { Status get_status() const; String get_running_scene() const; - Error run(const String &p_scene, const String &p_write_movie = ""); + Error run(const String &p_scene, const String &p_write_movie = "", List *p_run_args = nullptr); void run_native_notify() { status = STATUS_PLAY; } void stop(); diff --git a/editor/gui/editor_run_bar.cpp b/editor/gui/editor_run_bar.cpp index 49bd212ac2f1..b3cbf61c7d45 100644 --- a/editor/gui/editor_run_bar.cpp +++ b/editor/gui/editor_run_bar.cpp @@ -42,8 +42,13 @@ #include "editor/gui/editor_quick_open_dialog.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" +#include "scene/gui/menu_button.h" #include "scene/gui/panel_container.h" +#ifndef _3D_DISABLED +#include "servers/xr_server.h" +#endif // _3D_DISABLED + EditorRunBar *EditorRunBar::singleton = nullptr; void EditorRunBar::_notification(int p_what) { @@ -124,33 +129,66 @@ void EditorRunBar::_write_movie_toggled(bool p_enabled) { } } -void EditorRunBar::_quick_run_selected(const String &p_file_path) { - play_custom_scene(p_file_path); +void EditorRunBar::_quick_run_selected(const String &p_file_path, int p_id) { + List play_args; + if (p_id == 0) { + // Play in regular mode, xr mode off + play_args.push_back("--xr-mode"); + play_args.push_back("off"); + } else if (p_id == 1) { + // Play in xr mode + play_args.push_back("--xr-mode"); + play_args.push_back("on"); + } + + play_custom_scene(p_file_path, &play_args); } -void EditorRunBar::_play_custom_pressed() { +void EditorRunBar::_play_custom_pressed(int p_id) { if (editor_run.get_status() == EditorRun::STATUS_STOP || current_mode != RunMode::RUN_CUSTOM) { stop_playing(); - EditorNode::get_singleton()->get_quick_open_dialog()->popup_dialog({ "PackedScene" }, callable_mp(this, &EditorRunBar::_quick_run_selected)); + EditorNode::get_singleton()->get_quick_open_dialog()->popup_dialog({ "PackedScene" }, callable_mp(this, &EditorRunBar::_quick_run_selected).bind(p_id)); play_custom_scene_button->set_pressed(false); } else { + List play_args; + if (p_id == 0) { + // Play in regular mode, xr mode off + play_args.push_back("--xr-mode"); + play_args.push_back("off"); + } else if (p_id == 1) { + // Play in xr mode + play_args.push_back("--xr-mode"); + play_args.push_back("on"); + } + // Reload if already running a custom scene. String last_custom_scene = run_custom_filename; // This is necessary to have a copy of the string. - play_custom_scene(last_custom_scene); + play_custom_scene(last_custom_scene, &play_args); } } -void EditorRunBar::_play_current_pressed() { +void EditorRunBar::_play_current_pressed(int p_id) { + List play_args; + if (p_id == 0) { + // Play in regular mode, xr mode off + play_args.push_back("--xr-mode"); + play_args.push_back("off"); + } else if (p_id == 1) { + // Play in xr mode + play_args.push_back("--xr-mode"); + play_args.push_back("on"); + } + if (editor_run.get_status() == EditorRun::STATUS_STOP || current_mode != RunMode::RUN_CURRENT) { - play_current_scene(); + play_current_scene(false, &play_args); } else { // Reload if already running the current scene. - play_current_scene(true); + play_current_scene(true, &play_args); } } -void EditorRunBar::_run_scene(const String &p_scene_path) { +void EditorRunBar::_run_scene(const String &p_scene_path, List *p_run_args) { ERR_FAIL_COND_MSG(current_mode == RUN_CUSTOM && p_scene_path.is_empty(), "Attempting to run a custom scene with an empty path."); if (editor_run.get_status() == EditorRun::STATUS_PLAY) { @@ -235,7 +273,7 @@ void EditorRunBar::_run_scene(const String &p_scene_path) { } EditorDebuggerNode::get_singleton()->start(); - Error error = editor_run.run(run_filename, write_movie_file); + Error error = editor_run.run(run_filename, write_movie_file, p_run_args); if (error != OK) { EditorDebuggerNode::get_singleton()->stop(); EditorNode::get_singleton()->show_accept(TTR("Could not start subprocess(es)!"), TTR("OK")); @@ -289,7 +327,7 @@ void EditorRunBar::play_main_scene(bool p_from_native) { } } -void EditorRunBar::play_current_scene(bool p_reload) { +void EditorRunBar::play_current_scene(bool p_reload, List *p_play_args) { String last_current_scene = run_current_filename; // This is necessary to have a copy of the string. EditorNode::get_singleton()->save_default_environment(); @@ -297,17 +335,17 @@ void EditorRunBar::play_current_scene(bool p_reload) { current_mode = RunMode::RUN_CURRENT; if (p_reload) { - _run_scene(last_current_scene); + _run_scene(last_current_scene, p_play_args); } else { - _run_scene(); + _run_scene("", p_play_args); } } -void EditorRunBar::play_custom_scene(const String &p_custom) { +void EditorRunBar::play_custom_scene(const String &p_custom, List *p_play_args) { stop_playing(); current_mode = RunMode::RUN_CUSTOM; - _run_scene(p_custom); + _run_scene(p_custom, p_play_args); } void EditorRunBar::stop_playing() { @@ -465,25 +503,55 @@ EditorRunBar::EditorRunBar() { main_hbox->add_child(run_native); run_native->connect("native_run", callable_mp(this, &EditorRunBar::_run_native)); - play_scene_button = memnew(Button); + bool add_play_xr_mode_options = false; +#ifndef _3D_DISABLED + if (OS::get_singleton()->has_feature("xr_editor") && + (XRServer::get_xr_mode() == XRServer::XRMODE_ON || + (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT && GLOBAL_GET("xr/openxr/enabled")))) { + // If this is the XR editor and openxr is enabled, we turn the `play_scene_button` and + // `play_custom_scene_button` into MenuButtons to provide the option to start a scene in + // either regular mode or XR mode. + add_play_xr_mode_options = true; + } +#endif // _3D_DISABLED + + if (add_play_xr_mode_options) { + MenuButton *menu_button = memnew(MenuButton); + PopupMenu *popup = menu_button->get_popup(); + popup->add_item(TTRC("Run Current Scene in Regular mode"), 0); + popup->add_item(TTRC("Run Current Scene in XR mode"), 1); + popup->connect(SceneStringName(id_pressed), callable_mp(this, &EditorRunBar::_play_current_pressed)); + play_scene_button = menu_button; + } else { + play_scene_button = memnew(Button); + play_scene_button->set_toggle_mode(true); + play_scene_button->connect(SceneStringName(pressed), callable_mp(this, &EditorRunBar::_play_current_pressed).bind(-1)); + } main_hbox->add_child(play_scene_button); play_scene_button->set_theme_type_variation("RunBarButton"); - play_scene_button->set_toggle_mode(true); play_scene_button->set_focus_mode(Control::FOCUS_NONE); play_scene_button->set_tooltip_text(TTRC("Run the currently edited scene.")); - play_scene_button->connect(SceneStringName(pressed), callable_mp(this, &EditorRunBar::_play_current_pressed)); ED_SHORTCUT_AND_COMMAND("editor/run_current_scene", TTRC("Run Current Scene"), Key::F6); ED_SHORTCUT_OVERRIDE("editor/run_current_scene", "macos", KeyModifierMask::META | Key::R); play_scene_button->set_shortcut(ED_GET_SHORTCUT("editor/run_current_scene")); - play_custom_scene_button = memnew(Button); + if (add_play_xr_mode_options) { + MenuButton *menu_button = memnew(MenuButton); + PopupMenu *popup = menu_button->get_popup(); + popup->add_item(TTRC("Run Specific Scene in Regular mode"), 0); + popup->add_item(TTRC("Run Specific Scene in XR mode"), 1); + popup->connect(SceneStringName(id_pressed), callable_mp(this, &EditorRunBar::_play_custom_pressed)); + play_custom_scene_button = menu_button; + } else { + play_custom_scene_button = memnew(Button); + play_custom_scene_button->set_toggle_mode(true); + play_custom_scene_button->connect(SceneStringName(pressed), callable_mp(this, &EditorRunBar::_play_custom_pressed).bind(-1)); + } main_hbox->add_child(play_custom_scene_button); play_custom_scene_button->set_theme_type_variation("RunBarButton"); - play_custom_scene_button->set_toggle_mode(true); play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE); play_custom_scene_button->set_tooltip_text(TTRC("Run a specific scene.")); - play_custom_scene_button->connect(SceneStringName(pressed), callable_mp(this, &EditorRunBar::_play_custom_pressed)); ED_SHORTCUT_AND_COMMAND("editor/run_specific_scene", TTRC("Run Specific Scene"), KeyModifierMask::CTRL | KeyModifierMask::SHIFT | Key::F5); ED_SHORTCUT_OVERRIDE("editor/run_specific_scene", "macos", KeyModifierMask::META | KeyModifierMask::SHIFT | Key::R); diff --git a/editor/gui/editor_run_bar.h b/editor/gui/editor_run_bar.h index b1e7e168473c..807ec5ca8967 100644 --- a/editor/gui/editor_run_bar.h +++ b/editor/gui/editor_run_bar.h @@ -78,12 +78,12 @@ class EditorRunBar : public MarginContainer { void _update_play_buttons(); void _write_movie_toggled(bool p_enabled); - void _quick_run_selected(const String &p_file_path); + void _quick_run_selected(const String &p_file_path, int p_id = -1); - void _play_current_pressed(); - void _play_custom_pressed(); + void _play_current_pressed(int p_id = -1); + void _play_custom_pressed(int p_id = -1); - void _run_scene(const String &p_scene_path = ""); + void _run_scene(const String &p_scene_path = "", List *p_run_args = nullptr); void _run_native(const Ref &p_preset); void _profiler_autostart_indicator_pressed(); @@ -96,8 +96,8 @@ class EditorRunBar : public MarginContainer { static EditorRunBar *get_singleton() { return singleton; } void play_main_scene(bool p_from_native = false); - void play_current_scene(bool p_reload = false); - void play_custom_scene(const String &p_custom); + void play_current_scene(bool p_reload = false, List *p_play_args = nullptr); + void play_custom_scene(const String &p_custom, List *p_play_args = nullptr); void stop_playing(); bool is_playing() const; diff --git a/platform/android/java/editor/src/horizonos/java/org/godotengine/editor/GodotEditor.kt b/platform/android/java/editor/src/horizonos/java/org/godotengine/editor/GodotEditor.kt index 9dc34f226729..0064f1e81c87 100644 --- a/platform/android/java/editor/src/horizonos/java/org/godotengine/editor/GodotEditor.kt +++ b/platform/android/java/editor/src/horizonos/java/org/godotengine/editor/GodotEditor.kt @@ -43,6 +43,19 @@ open class GodotEditor : BaseGodotEditor() { companion object { private val TAG = GodotEditor::class.java.simpleName + /** Default behavior, means we check project settings **/ + private const val XR_MODE_DEFAULT = "default" + + /** + * Ignore project settings, OpenXR is disabled + */ + private const val XR_MODE_OFF = "off" + + /** + * Ignore project settings, OpenXR is enabled + */ + private const val XR_MODE_ON = "on" + internal val XR_RUN_GAME_INFO = EditorWindowInfo(GodotXRGame::class.java, 1667, ":GodotXRGame") internal val USE_SCENE_PERMISSIONS = listOf("com.oculus.permission.USE_SCENE", "horizonos.permission.USE_SCENE") @@ -58,15 +71,14 @@ open class GodotEditor : BaseGodotEditor() { override fun retrieveEditorWindowInfo(args: Array): EditorWindowInfo { var hasEditor = false - var xrModeOn = false + var xrMode = XR_MODE_DEFAULT var i = 0 while (i < args.size) { when (args[i++]) { EDITOR_ARG, EDITOR_ARG_SHORT, EDITOR_PROJECT_MANAGER_ARG, EDITOR_PROJECT_MANAGER_ARG_SHORT -> hasEditor = true XR_MODE_ARG -> { - val argValue = args[i++] - xrModeOn = xrModeOn || ("on" == argValue) + xrMode = args[i++] } } } @@ -74,7 +86,8 @@ open class GodotEditor : BaseGodotEditor() { return if (hasEditor) { EDITOR_MAIN_INFO } else { - val openxrEnabled = GodotLib.getGlobal("xr/openxr/enabled").toBoolean() + val openxrEnabled = xrMode == XR_MODE_ON || + (xrMode == XR_MODE_DEFAULT && GodotLib.getGlobal("xr/openxr/enabled").toBoolean()) if (openxrEnabled && isNativeXRDevice()) { XR_RUN_GAME_INFO } else {