Skip to content

Commit b4f25b1

Browse files
committed
Clean up the XR editor logic
- Coalesce common logic into the `main` flavor to avoid duplication - Code cleanup
1 parent d33da79 commit b4f25b1

File tree

13 files changed

+86
-214
lines changed

13 files changed

+86
-214
lines changed

platform/android/export/export_plugin.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2840,6 +2840,13 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP
28402840
command_line_strings.push_back("--xr_mode_openxr");
28412841
} else { // XRMode.REGULAR is the default.
28422842
command_line_strings.push_back("--xr_mode_regular");
2843+
2844+
// Also override the 'xr/openxr/enabled' project setting.
2845+
// This is useful for multi-platforms projects supporting both XR and non-XR devices. The project would need
2846+
// to enable openxr for development, and would create multiple XR and non-XR export presets.
2847+
// These command line args ensure that the non-XR export presets will have openxr disabled.
2848+
command_line_strings.push_back("--xr-mode");
2849+
command_line_strings.push_back("off");
28432850
}
28442851

28452852
bool immersive = p_preset->get("screen/immersive_mode");

platform/android/java/editor/src/android/java/org/godotengine/editor/GodotEditor.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,4 @@ package org.godotengine.editor
3535
*
3636
* This is the implementation of the editor used when running on regular Android devices.
3737
*/
38-
open class GodotEditor : BaseGodotEditor() {
39-
}
38+
open class GodotEditor : BaseGodotEditor()

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,8 @@
5757

5858
<activity
5959
android:name=".GodotXRGame"
60-
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
61-
android:process=":GodotXRGame"
62-
android:launchMode="singleTask"
63-
android:icon="@mipmap/ic_play_window"
64-
android:label="@string/godot_game_activity_name"
6560
android:exported="false"
66-
android:screenOrientation="landscape"
67-
android:resizeableActivity="false"
68-
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
61+
tools:node="merge">
6962
<intent-filter>
7063
<action android:name="android.intent.action.MAIN" />
7164
<category android:name="android.intent.category.DEFAULT" />

platform/android/java/editor/src/horizonos/java/org/godotengine/editor/GodotEditor.kt

Lines changed: 5 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -30,76 +30,17 @@
3030

3131
package org.godotengine.editor
3232

33-
import org.godotengine.godot.GodotLib
34-
import org.godotengine.godot.utils.isNativeXRDevice
35-
3633
/**
3734
* Primary window of the Godot Editor.
3835
*
3936
* This is the implementation of the editor used when running on HorizonOS devices.
4037
*/
4138
open class GodotEditor : BaseGodotEditor() {
4239

43-
companion object {
44-
private val TAG = GodotEditor::class.java.simpleName
45-
46-
/** Default behavior, means we check project settings **/
47-
private const val XR_MODE_DEFAULT = "default"
48-
49-
/**
50-
* Ignore project settings, OpenXR is disabled
51-
*/
52-
private const val XR_MODE_OFF = "off"
53-
54-
/**
55-
* Ignore project settings, OpenXR is enabled
56-
*/
57-
private const val XR_MODE_ON = "on"
58-
59-
internal val XR_RUN_GAME_INFO = EditorWindowInfo(GodotXRGame::class.java, 1667, ":GodotXRGame")
60-
61-
internal val USE_SCENE_PERMISSIONS = listOf("com.oculus.permission.USE_SCENE", "horizonos.permission.USE_SCENE")
62-
}
63-
64-
override fun getExcludedPermissions(): MutableSet<String> {
65-
val excludedPermissions = super.getExcludedPermissions()
66-
// The USE_SCENE permission is requested when the "xr/openxr/enabled" project setting
67-
// is enabled.
68-
excludedPermissions.addAll(USE_SCENE_PERMISSIONS)
69-
return excludedPermissions
70-
}
71-
72-
override fun retrieveEditorWindowInfo(args: Array<String>): EditorWindowInfo {
73-
var hasEditor = false
74-
var xrMode = XR_MODE_DEFAULT
75-
76-
var i = 0
77-
while (i < args.size) {
78-
when (args[i++]) {
79-
EDITOR_ARG, EDITOR_ARG_SHORT, EDITOR_PROJECT_MANAGER_ARG, EDITOR_PROJECT_MANAGER_ARG_SHORT -> hasEditor = true
80-
XR_MODE_ARG -> {
81-
xrMode = args[i++]
82-
}
83-
}
84-
}
85-
86-
return if (hasEditor) {
87-
EDITOR_MAIN_INFO
88-
} else {
89-
val openxrEnabled = xrMode == XR_MODE_ON ||
90-
(xrMode == XR_MODE_DEFAULT && GodotLib.getGlobal("xr/openxr/enabled").toBoolean())
91-
if (openxrEnabled && isNativeXRDevice()) {
92-
XR_RUN_GAME_INFO
93-
} else {
94-
RUN_GAME_INFO
95-
}
96-
}
97-
}
98-
99-
override fun getEditorWindowInfoForInstanceId(instanceId: Int): EditorWindowInfo? {
100-
return when (instanceId) {
101-
XR_RUN_GAME_INFO.windowId -> XR_RUN_GAME_INFO
102-
else -> super.getEditorWindowInfoForInstanceId(instanceId)
103-
}
40+
override fun getXRRuntimePermissions(): MutableSet<String> {
41+
val xrRuntimePermissions = super.getXRRuntimePermissions()
42+
xrRuntimePermissions.add("com.oculus.permission.USE_SCENE")
43+
xrRuntimePermissions.add("horizonos.permission.USE_SCENE")
44+
return xrRuntimePermissions
10445
}
10546
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@
7171
android:defaultWidth="@dimen/editor_default_window_width"
7272
android:defaultHeight="@dimen/editor_default_window_height" />
7373
</activity>
74+
<activity
75+
android:name=".GodotXRGame"
76+
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
77+
android:process=":GodotXRGame"
78+
android:launchMode="singleTask"
79+
android:icon="@mipmap/ic_play_window"
80+
android:label="@string/godot_game_activity_name"
81+
android:exported="false"
82+
android:screenOrientation="landscape"
83+
android:resizeableActivity="false"
84+
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
85+
</activity>
7486
</application>
7587

7688
</manifest>

platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,12 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
4747
import androidx.window.layout.WindowMetricsCalculator
4848
import org.godotengine.editor.utils.signApk
4949
import org.godotengine.editor.utils.verifyApk
50+
import org.godotengine.godot.BuildConfig
5051
import org.godotengine.godot.GodotActivity
5152
import org.godotengine.godot.GodotLib
5253
import org.godotengine.godot.error.Error
5354
import org.godotengine.godot.utils.PermissionsUtil
5455
import org.godotengine.godot.utils.ProcessPhoenix
55-
import org.godotengine.godot.utils.isHorizonOSDevice
56-
import org.godotengine.godot.utils.isPicoOSDevice
5756
import org.godotengine.godot.utils.isNativeXRDevice
5857
import java.util.*
5958
import kotlin.math.min
@@ -93,6 +92,20 @@ abstract class BaseGodotEditor : GodotActivity() {
9392
// Info for the various classes used by the editor
9493
internal val EDITOR_MAIN_INFO = EditorWindowInfo(GodotEditor::class.java, 777, "")
9594
internal val RUN_GAME_INFO = EditorWindowInfo(GodotGame::class.java, 667, ":GodotGame", LaunchPolicy.AUTO, true)
95+
internal val XR_RUN_GAME_INFO = EditorWindowInfo(GodotXRGame::class.java, 1667, ":GodotXRGame")
96+
97+
/** Default behavior, means we check project settings **/
98+
private const val XR_MODE_DEFAULT = "default"
99+
100+
/**
101+
* Ignore project settings, OpenXR is disabled
102+
*/
103+
private const val XR_MODE_OFF = "off"
104+
105+
/**
106+
* Ignore project settings, OpenXR is enabled
107+
*/
108+
private const val XR_MODE_ON = "on"
96109

97110
/**
98111
* Sets of constants to specify the window to use to run the project.
@@ -129,8 +142,7 @@ abstract class BaseGodotEditor : GodotActivity() {
129142
*
130143
* The permissions in this set will be requested on demand based on use cases.
131144
*/
132-
@CallSuper
133-
protected open fun getExcludedPermissions(): MutableSet<String> {
145+
private fun getExcludedPermissions(): MutableSet<String> {
134146
val excludedPermissions = mutableSetOf(
135147
// The RECORD_AUDIO permission is requested when the "audio/driver/enable_input" project
136148
// setting is enabled.
@@ -144,9 +156,21 @@ abstract class BaseGodotEditor : GodotActivity() {
144156
Manifest.permission.REQUEST_INSTALL_PACKAGES,
145157
)
146158
}
159+
160+
// XR runtime permissions should only be requested when the "xr/openxr/enabled" project setting
161+
// is enabled.
162+
excludedPermissions.addAll(getXRRuntimePermissions())
147163
return excludedPermissions
148164
}
149165

166+
/**
167+
* Set of permissions to request when the "xr/openxr/enabled" project setting is enabled.
168+
*/
169+
@CallSuper
170+
protected open fun getXRRuntimePermissions(): MutableSet<String> {
171+
return mutableSetOf()
172+
}
173+
150174
override fun onCreate(savedInstanceState: Bundle?) {
151175
installSplashScreen()
152176

@@ -208,27 +232,38 @@ abstract class BaseGodotEditor : GodotActivity() {
208232

209233
final override fun getCommandLine() = commandLineParams
210234

211-
protected open fun retrieveEditorWindowInfo(args: Array<String>): EditorWindowInfo {
235+
protected fun retrieveEditorWindowInfo(args: Array<String>): EditorWindowInfo {
212236
var hasEditor = false
237+
var xrMode = XR_MODE_DEFAULT
213238

214239
var i = 0
215240
while (i < args.size) {
216241
when (args[i++]) {
217242
EDITOR_ARG, EDITOR_ARG_SHORT, EDITOR_PROJECT_MANAGER_ARG, EDITOR_PROJECT_MANAGER_ARG_SHORT -> hasEditor = true
243+
XR_MODE_ARG -> {
244+
xrMode = args[i++]
245+
}
218246
}
219247
}
220248

221249
return if (hasEditor) {
222250
EDITOR_MAIN_INFO
223251
} else {
224-
RUN_GAME_INFO
252+
val openxrEnabled = xrMode == XR_MODE_ON ||
253+
(xrMode == XR_MODE_DEFAULT && GodotLib.getGlobal("xr/openxr/enabled").toBoolean())
254+
if (openxrEnabled && isNativeXRDevice(applicationContext)) {
255+
XR_RUN_GAME_INFO
256+
} else {
257+
RUN_GAME_INFO
258+
}
225259
}
226260
}
227261

228-
protected open fun getEditorWindowInfoForInstanceId(instanceId: Int): EditorWindowInfo? {
262+
private fun getEditorWindowInfoForInstanceId(instanceId: Int): EditorWindowInfo? {
229263
return when (instanceId) {
230264
RUN_GAME_INFO.windowId -> RUN_GAME_INFO
231265
EDITOR_MAIN_INFO.windowId -> EDITOR_MAIN_INFO
266+
XR_RUN_GAME_INFO.windowId -> XR_RUN_GAME_INFO
232267
else -> null
233268
}
234269
}
@@ -417,8 +452,8 @@ abstract class BaseGodotEditor : GodotActivity() {
417452

418453
return when (policy) {
419454
LaunchPolicy.AUTO -> {
420-
if (isHorizonOSDevice()) {
421-
// Horizon OS UX is more desktop-like and has support for launching adjacent
455+
if (isNativeXRDevice(applicationContext)) {
456+
// Native XR devices are more desktop-like and have support for launching adjacent
422457
// windows. So we always want to launch in adjacent mode when auto is selected.
423458
LaunchPolicy.ADJACENT
424459
} else {
@@ -450,12 +485,6 @@ abstract class BaseGodotEditor : GodotActivity() {
450485
* Returns true the if the device supports picture-in-picture (PiP)
451486
*/
452487
protected open fun hasPiPSystemFeature(): Boolean {
453-
if (isNativeXRDevice()) {
454-
// Known native XR devices do not support PiP.
455-
// Will need to revisit as they update their OS.
456-
return false
457-
}
458-
459488
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
460489
packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
461490
}
@@ -534,15 +563,15 @@ abstract class BaseGodotEditor : GodotActivity() {
534563

535564
override fun supportsFeature(featureTag: String): Boolean {
536565
if (featureTag == "xr_editor") {
537-
return isNativeXRDevice()
566+
return isNativeXRDevice(applicationContext)
538567
}
539568

540569
if (featureTag == "horizonos") {
541-
return isHorizonOSDevice()
570+
return BuildConfig.FLAVOR == "horizonos"
542571
}
543572

544573
if (featureTag == "picoos") {
545-
return isPicoOSDevice()
574+
return BuildConfig.FLAVOR == "picoos"
546575
}
547576

548577
return false

platform/android/java/editor/src/horizonos/java/org/godotengine/editor/GodotXRGame.kt renamed to platform/android/java/editor/src/main/java/org/godotengine/editor/GodotXRGame.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ open class GodotXRGame: GodotGame() {
5959
override fun getProjectPermissionsToEnable(): MutableList<String> {
6060
val permissionsToEnable = super.getProjectPermissionsToEnable()
6161

62-
val openxrEnabled = GodotLib.getGlobal("xr/openxr/enabled").toBoolean()
63-
if (openxrEnabled) {
62+
val xrRuntimePermission = getXRRuntimePermissions()
63+
if (xrRuntimePermission.isNotEmpty() && GodotLib.getGlobal("xr/openxr/enabled").toBoolean()) {
6464
// We only request permissions when the `automatically_request_runtime_permissions`
6565
// project setting is enabled.
6666
// If the project setting is not defined, we fall-back to the default behavior which is
@@ -69,7 +69,7 @@ open class GodotXRGame: GodotGame() {
6969
val automaticPermissionsRequestEnabled = automaticallyRequestPermissionsSetting.isNullOrEmpty() ||
7070
automaticallyRequestPermissionsSetting.toBoolean()
7171
if (automaticPermissionsRequestEnabled) {
72-
permissionsToEnable.addAll(USE_SCENE_PERMISSIONS)
72+
permissionsToEnable.addAll(xrRuntimePermission)
7373
}
7474
}
7575

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources>
3-
<dimen name="editor_default_window_height">640dp</dimen>
3+
<dimen name="editor_default_window_height">720dp</dimen>
44
<dimen name="editor_default_window_width">1024dp</dimen>
55
</resources>

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,8 @@
2929

3030
<activity
3131
android:name=".GodotXRGame"
32-
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
33-
android:process=":GodotXRGame"
34-
android:launchMode="singleTask"
35-
android:icon="@mipmap/ic_play_window"
36-
android:label="@string/godot_game_activity_name"
3732
android:exported="false"
38-
android:screenOrientation="landscape"
39-
android:resizeableActivity="false"
40-
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
33+
tools:node="merge">
4134
<intent-filter>
4235
<action android:name="android.intent.action.MAIN" />
4336
<category android:name="android.intent.category.DEFAULT" />

platform/android/java/editor/src/picoos/java/org/godotengine/editor/GodotEditor.kt

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -30,53 +30,9 @@
3030

3131
package org.godotengine.editor
3232

33-
import org.godotengine.godot.GodotLib
34-
import org.godotengine.godot.utils.isNativeXRDevice
35-
3633
/**
3734
* Primary window of the Godot Editor.
3835
*
3936
* This is the implementation of the editor used when running on PicoOS devices.
4037
*/
41-
open class GodotEditor : BaseGodotEditor() {
42-
43-
companion object {
44-
private val TAG = GodotEditor::class.java.simpleName
45-
46-
internal val XR_RUN_GAME_INFO = EditorWindowInfo(GodotXRGame::class.java, 1667, ":GodotXRGame")
47-
}
48-
49-
override fun retrieveEditorWindowInfo(args: Array<String>): EditorWindowInfo {
50-
var hasEditor = false
51-
var xrModeOn = false
52-
53-
var i = 0
54-
while (i < args.size) {
55-
when (args[i++]) {
56-
EDITOR_ARG, EDITOR_ARG_SHORT, EDITOR_PROJECT_MANAGER_ARG, EDITOR_PROJECT_MANAGER_ARG_SHORT -> hasEditor = true
57-
XR_MODE_ARG -> {
58-
val argValue = args[i++]
59-
xrModeOn = xrModeOn || ("on" == argValue)
60-
}
61-
}
62-
}
63-
64-
return if (hasEditor) {
65-
EDITOR_MAIN_INFO
66-
} else {
67-
val openxrEnabled = GodotLib.getGlobal("xr/openxr/enabled").toBoolean()
68-
if (openxrEnabled && isNativeXRDevice()) {
69-
XR_RUN_GAME_INFO
70-
} else {
71-
RUN_GAME_INFO
72-
}
73-
}
74-
}
75-
76-
override fun getEditorWindowInfoForInstanceId(instanceId: Int): EditorWindowInfo? {
77-
return when (instanceId) {
78-
XR_RUN_GAME_INFO.windowId -> XR_RUN_GAME_INFO
79-
else -> super.getEditorWindowInfoForInstanceId(instanceId)
80-
}
81-
}
82-
}
38+
open class GodotEditor : BaseGodotEditor()

0 commit comments

Comments
 (0)