Skip to content

Commit f7c6f00

Browse files
committed
Merge pull request #103972 from m4gr3d/xr_editor_hybrid_support
Add support for running hybrid apps from the XR editor
2 parents 5abed52 + 09f5be7 commit f7c6f00

File tree

20 files changed

+438
-62
lines changed

20 files changed

+438
-62
lines changed

editor/debugger/editor_debugger_node.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,7 @@ void EditorDebuggerNode::stop(bool p_force) {
311311

312312
// Also close all debugging sessions.
313313
_for_all(tabs, [&](ScriptEditorDebugger *dbg) {
314-
if (dbg->is_session_active()) {
315-
dbg->_stop_and_notify();
316-
}
314+
dbg->_stop_and_notify();
317315
});
318316
_break_state_changed();
319317
breakpoints.clear();

editor/editor_node.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2176,7 +2176,7 @@ void EditorNode::try_autosave() {
21762176
Node *scene = editor_data.get_edited_scene_root();
21772177

21782178
if (scene && !scene->get_scene_file_path().is_empty()) { // Only autosave if there is a scene and if it has a path.
2179-
_save_scene(scene->get_scene_file_path());
2179+
_save_scene(scene->get_scene_file_path(), -1, false);
21802180
}
21812181
}
21822182
_menu_option(SCENE_SAVE_ALL_SCENES);

platform/android/SCsub

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ android_files = [
3232
"rendering_context_driver_vulkan_android.cpp",
3333
"variant/callable_jni.cpp",
3434
"dialog_utils_jni.cpp",
35-
"game_menu_utils_jni.cpp",
35+
"editor/game_menu_utils_jni.cpp",
36+
"editor/editor_utils_jni.cpp",
3637
]
3738

3839
env_android = env.Clone()
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/**************************************************************************/
2+
/* editor_utils_jni.cpp */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#include "editor_utils_jni.h"
32+
33+
#include "jni_utils.h"
34+
35+
#ifdef TOOLS_ENABLED
36+
#include "editor/gui/editor_run_bar.h"
37+
#include "main/main.h"
38+
#endif
39+
40+
extern "C" {
41+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_EditorUtils_runScene(JNIEnv *p_env, jclass, jstring p_scene, jobjectArray p_scene_args) {
42+
#ifdef TOOLS_ENABLED
43+
Vector<String> scene_args;
44+
jint length = p_env->GetArrayLength(p_scene_args);
45+
for (jint i = 0; i < length; ++i) {
46+
jstring j_arg = (jstring)p_env->GetObjectArrayElement(p_scene_args, i);
47+
String arg = jstring_to_string(j_arg, p_env);
48+
scene_args.push_back(arg);
49+
p_env->DeleteLocalRef(j_arg);
50+
}
51+
52+
String scene = jstring_to_string(p_scene, p_env);
53+
54+
EditorRunBar *editor_run_bar = EditorRunBar::get_singleton();
55+
if (editor_run_bar != nullptr) {
56+
if (scene.is_empty()) {
57+
editor_run_bar->play_main_scene(false);
58+
} else {
59+
editor_run_bar->play_custom_scene(scene, scene_args);
60+
}
61+
} else {
62+
List<String> args;
63+
64+
for (const String &a : Main::get_forwardable_cli_arguments(Main::CLI_SCOPE_PROJECT)) {
65+
args.push_back(a);
66+
}
67+
68+
for (const String &arg : scene_args) {
69+
args.push_back(arg);
70+
}
71+
72+
if (!scene.is_empty()) {
73+
args.push_back("--scene");
74+
args.push_back(scene);
75+
}
76+
77+
Error err = OS::get_singleton()->create_instance(args);
78+
ERR_FAIL_COND(err);
79+
}
80+
#endif
81+
}
82+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**************************************************************************/
2+
/* editor_utils_jni.h */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#pragma once
32+
33+
#include <jni.h>
34+
35+
extern "C" {
36+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_EditorUtils_runScene(JNIEnv *p_env, jclass, jstring p_scene, jobjectArray p_scene_args);
37+
}

platform/android/game_menu_utils_jni.cpp renamed to platform/android/editor/game_menu_utils_jni.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static GameViewPlugin *_get_game_view_plugin() {
4545

4646
extern "C" {
4747

48-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSuspend(JNIEnv *env, jclass clazz, jboolean enabled) {
48+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setSuspend(JNIEnv *env, jclass clazz, jboolean enabled) {
4949
#ifdef TOOLS_ENABLED
5050
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
5151
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
@@ -54,7 +54,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSuspend
5454
#endif
5555
}
5656

57-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_nextFrame(JNIEnv *env, jclass clazz) {
57+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_nextFrame(JNIEnv *env, jclass clazz) {
5858
#ifdef TOOLS_ENABLED
5959
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
6060
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
@@ -63,7 +63,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_nextFrame(
6363
#endif
6464
}
6565

66-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setNodeType(JNIEnv *env, jclass clazz, jint type) {
66+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setNodeType(JNIEnv *env, jclass clazz, jint type) {
6767
#ifdef TOOLS_ENABLED
6868
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
6969
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
@@ -72,7 +72,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setNodeTyp
7272
#endif
7373
}
7474

75-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectMode(JNIEnv *env, jclass clazz, jint mode) {
75+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setSelectMode(JNIEnv *env, jclass clazz, jint mode) {
7676
#ifdef TOOLS_ENABLED
7777
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
7878
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
@@ -81,7 +81,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectM
8181
#endif
8282
}
8383

84-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectionVisible(JNIEnv *env, jclass clazz, jboolean visible) {
84+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setSelectionVisible(JNIEnv *env, jclass clazz, jboolean visible) {
8585
#ifdef TOOLS_ENABLED
8686
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
8787
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
@@ -90,7 +90,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelecti
9090
#endif
9191
}
9292

93-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraOverride(JNIEnv *env, jclass clazz, jboolean enabled) {
93+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setCameraOverride(JNIEnv *env, jclass clazz, jboolean enabled) {
9494
#ifdef TOOLS_ENABLED
9595
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
9696
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
@@ -99,7 +99,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraO
9999
#endif
100100
}
101101

102-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraManipulateMode(JNIEnv *env, jclass clazz, jint mode) {
102+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setCameraManipulateMode(JNIEnv *env, jclass clazz, jint mode) {
103103
#ifdef TOOLS_ENABLED
104104
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
105105
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
@@ -108,7 +108,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraM
108108
#endif
109109
}
110110

111-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamera2DPosition(JNIEnv *env, jclass clazz) {
111+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_resetCamera2DPosition(JNIEnv *env, jclass clazz) {
112112
#ifdef TOOLS_ENABLED
113113
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
114114
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
@@ -117,7 +117,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamer
117117
#endif
118118
}
119119

120-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamera3DPosition(JNIEnv *env, jclass clazz) {
120+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_resetCamera3DPosition(JNIEnv *env, jclass clazz) {
121121
#ifdef TOOLS_ENABLED
122122
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
123123
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
@@ -126,15 +126,15 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamer
126126
#endif
127127
}
128128

129-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_playMainScene(JNIEnv *env, jclass clazz) {
129+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_playMainScene(JNIEnv *env, jclass clazz) {
130130
#ifdef TOOLS_ENABLED
131131
if (EditorInterface::get_singleton()) {
132132
EditorInterface::get_singleton()->play_main_scene();
133133
}
134134
#endif
135135
}
136136

137-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setDebugMuteAudio(JNIEnv *env, jclass clazz, jboolean enabled) {
137+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setDebugMuteAudio(JNIEnv *env, jclass clazz, jboolean enabled) {
138138
#ifdef TOOLS_ENABLED
139139
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
140140
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {

platform/android/game_menu_utils_jni.h renamed to platform/android/editor/game_menu_utils_jni.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@
3333
#include <jni.h>
3434

3535
extern "C" {
36-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSuspend(JNIEnv *env, jclass clazz, jboolean enabled);
37-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_nextFrame(JNIEnv *env, jclass clazz);
38-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setNodeType(JNIEnv *env, jclass clazz, jint type);
39-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectMode(JNIEnv *env, jclass clazz, jint mode);
40-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectionVisible(JNIEnv *env, jclass clazz, jboolean visible);
41-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraOverride(JNIEnv *env, jclass clazz, jboolean enabled);
42-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraManipulateMode(JNIEnv *env, jclass clazz, jint mode);
43-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamera2DPosition(JNIEnv *env, jclass clazz);
44-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamera3DPosition(JNIEnv *env, jclass clazz);
45-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_playMainScene(JNIEnv *env, jclass clazz);
46-
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setDebugMuteAudio(JNIEnv *env, jclass clazz, jboolean enabled);
36+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setSuspend(JNIEnv *env, jclass clazz, jboolean enabled);
37+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_nextFrame(JNIEnv *env, jclass clazz);
38+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setNodeType(JNIEnv *env, jclass clazz, jint type);
39+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setSelectMode(JNIEnv *env, jclass clazz, jint mode);
40+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setSelectionVisible(JNIEnv *env, jclass clazz, jboolean visible);
41+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setCameraOverride(JNIEnv *env, jclass clazz, jboolean enabled);
42+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setCameraManipulateMode(JNIEnv *env, jclass clazz, jint mode);
43+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_resetCamera2DPosition(JNIEnv *env, jclass clazz);
44+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_resetCamera3DPosition(JNIEnv *env, jclass clazz);
45+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_playMainScene(JNIEnv *env, jclass clazz);
46+
JNIEXPORT void JNICALL Java_org_godotengine_godot_editor_utils_GameMenuUtils_setDebugMuteAudio(JNIEnv *env, jclass clazz, jboolean enabled);
4747
}

platform/android/java/editor/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ android {
180180
}
181181

182182
dependencies {
183+
implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
184+
183185
implementation "androidx.fragment:fragment:$versions.fragmentVersion"
184186
implementation project(":lib")
185187

platform/android/java/editor/src/main/AndroidManifest.xml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,22 @@
6060
<category android:name="android.intent.category.DEFAULT" />
6161
<category android:name="android.intent.category.LAUNCHER" />
6262
</intent-filter>
63+
64+
<!-- Intent filter used to intercept hybrid PANEL launch for the current editor project, and route it
65+
properly through the editor 'run' logic (e.g: debugger setup) -->
66+
<intent-filter>
67+
<action android:name="android.intent.action.MAIN" />
68+
<category android:name="android.intent.category.DEFAULT" />
69+
<category android:name="org.godotengine.xr.hybrid.PANEL" />
70+
</intent-filter>
71+
72+
<!-- Intent filter used to intercept hybrid IMMERSIVE launch for the current editor project, and route it
73+
properly through the editor 'run' logic (e.g: debugger setup) -->
74+
<intent-filter>
75+
<action android:name="android.intent.action.MAIN" />
76+
<category android:name="android.intent.category.DEFAULT" />
77+
<category android:name="org.godotengine.xr.hybrid.IMMERSIVE" />
78+
</intent-filter>
6379
</activity>
6480
<activity
6581
android:name=".GodotGame"
@@ -101,8 +117,7 @@
101117
android:autoRemoveFromRecents="true"
102118
android:screenOrientation="landscape"
103119
android:resizeableActivity="false"
104-
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
105-
</activity>
120+
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" />
106121

107122
<!--
108123
We remove this meta-data originating from the vendors plugin as we only need the loader for

0 commit comments

Comments
 (0)