Skip to content

Commit

Permalink
Merge pull request godotengine#101645 from m4gr3d/disable_xr_mode_for…
Browse files Browse the repository at this point in the history
…_regular_launch

Clean up the XR editor logic
  • Loading branch information
Repiteo committed Jan 17, 2025
2 parents 02ea1f8 + b4f25b1 commit 041cb20
Show file tree
Hide file tree
Showing 13 changed files with 86 additions and 214 deletions.
7 changes: 7 additions & 0 deletions platform/android/export/export_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2840,6 +2840,13 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP
command_line_strings.push_back("--xr_mode_openxr");
} else { // XRMode.REGULAR is the default.
command_line_strings.push_back("--xr_mode_regular");

// Also override the 'xr/openxr/enabled' project setting.
// This is useful for multi-platforms projects supporting both XR and non-XR devices. The project would need
// to enable openxr for development, and would create multiple XR and non-XR export presets.
// These command line args ensure that the non-XR export presets will have openxr disabled.
command_line_strings.push_back("--xr-mode");
command_line_strings.push_back("off");
}

bool immersive = p_preset->get("screen/immersive_mode");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,4 @@ package org.godotengine.editor
*
* This is the implementation of the editor used when running on regular Android devices.
*/
open class GodotEditor : BaseGodotEditor() {
}
open class GodotEditor : BaseGodotEditor()
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,8 @@

<activity
android:name=".GodotXRGame"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
android:process=":GodotXRGame"
android:launchMode="singleTask"
android:icon="@mipmap/ic_play_window"
android:label="@string/godot_game_activity_name"
android:exported="false"
android:screenOrientation="landscape"
android:resizeableActivity="false"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
tools:node="merge">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,76 +30,17 @@

package org.godotengine.editor

import org.godotengine.godot.GodotLib
import org.godotengine.godot.utils.isNativeXRDevice

/**
* Primary window of the Godot Editor.
*
* This is the implementation of the editor used when running on HorizonOS devices.
*/
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")
}

override fun getExcludedPermissions(): MutableSet<String> {
val excludedPermissions = super.getExcludedPermissions()
// The USE_SCENE permission is requested when the "xr/openxr/enabled" project setting
// is enabled.
excludedPermissions.addAll(USE_SCENE_PERMISSIONS)
return excludedPermissions
}

override fun retrieveEditorWindowInfo(args: Array<String>): EditorWindowInfo {
var hasEditor = 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 -> {
xrMode = args[i++]
}
}
}

return if (hasEditor) {
EDITOR_MAIN_INFO
} else {
val openxrEnabled = xrMode == XR_MODE_ON ||
(xrMode == XR_MODE_DEFAULT && GodotLib.getGlobal("xr/openxr/enabled").toBoolean())
if (openxrEnabled && isNativeXRDevice()) {
XR_RUN_GAME_INFO
} else {
RUN_GAME_INFO
}
}
}

override fun getEditorWindowInfoForInstanceId(instanceId: Int): EditorWindowInfo? {
return when (instanceId) {
XR_RUN_GAME_INFO.windowId -> XR_RUN_GAME_INFO
else -> super.getEditorWindowInfoForInstanceId(instanceId)
}
override fun getXRRuntimePermissions(): MutableSet<String> {
val xrRuntimePermissions = super.getXRRuntimePermissions()
xrRuntimePermissions.add("com.oculus.permission.USE_SCENE")
xrRuntimePermissions.add("horizonos.permission.USE_SCENE")
return xrRuntimePermissions
}
}
12 changes: 12 additions & 0 deletions platform/android/java/editor/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@
android:defaultWidth="@dimen/editor_default_window_width"
android:defaultHeight="@dimen/editor_default_window_height" />
</activity>
<activity
android:name=".GodotXRGame"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
android:process=":GodotXRGame"
android:launchMode="singleTask"
android:icon="@mipmap/ic_play_window"
android:label="@string/godot_game_activity_name"
android:exported="false"
android:screenOrientation="landscape"
android:resizeableActivity="false"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,12 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.window.layout.WindowMetricsCalculator
import org.godotengine.editor.utils.signApk
import org.godotengine.editor.utils.verifyApk
import org.godotengine.godot.BuildConfig
import org.godotengine.godot.GodotActivity
import org.godotengine.godot.GodotLib
import org.godotengine.godot.error.Error
import org.godotengine.godot.utils.PermissionsUtil
import org.godotengine.godot.utils.ProcessPhoenix
import org.godotengine.godot.utils.isHorizonOSDevice
import org.godotengine.godot.utils.isPicoOSDevice
import org.godotengine.godot.utils.isNativeXRDevice
import java.util.*
import kotlin.math.min
Expand Down Expand Up @@ -93,6 +92,20 @@ abstract class BaseGodotEditor : GodotActivity() {
// Info for the various classes used by the editor
internal val EDITOR_MAIN_INFO = EditorWindowInfo(GodotEditor::class.java, 777, "")
internal val RUN_GAME_INFO = EditorWindowInfo(GodotGame::class.java, 667, ":GodotGame", LaunchPolicy.AUTO, true)
internal val XR_RUN_GAME_INFO = EditorWindowInfo(GodotXRGame::class.java, 1667, ":GodotXRGame")

/** 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"

/**
* Sets of constants to specify the window to use to run the project.
Expand Down Expand Up @@ -129,8 +142,7 @@ abstract class BaseGodotEditor : GodotActivity() {
*
* The permissions in this set will be requested on demand based on use cases.
*/
@CallSuper
protected open fun getExcludedPermissions(): MutableSet<String> {
private fun getExcludedPermissions(): MutableSet<String> {
val excludedPermissions = mutableSetOf(
// The RECORD_AUDIO permission is requested when the "audio/driver/enable_input" project
// setting is enabled.
Expand All @@ -144,9 +156,21 @@ abstract class BaseGodotEditor : GodotActivity() {
Manifest.permission.REQUEST_INSTALL_PACKAGES,
)
}

// XR runtime permissions should only be requested when the "xr/openxr/enabled" project setting
// is enabled.
excludedPermissions.addAll(getXRRuntimePermissions())
return excludedPermissions
}

/**
* Set of permissions to request when the "xr/openxr/enabled" project setting is enabled.
*/
@CallSuper
protected open fun getXRRuntimePermissions(): MutableSet<String> {
return mutableSetOf()
}

override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()

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

final override fun getCommandLine() = commandLineParams

protected open fun retrieveEditorWindowInfo(args: Array<String>): EditorWindowInfo {
protected fun retrieveEditorWindowInfo(args: Array<String>): EditorWindowInfo {
var hasEditor = 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 -> {
xrMode = args[i++]
}
}
}

return if (hasEditor) {
EDITOR_MAIN_INFO
} else {
RUN_GAME_INFO
val openxrEnabled = xrMode == XR_MODE_ON ||
(xrMode == XR_MODE_DEFAULT && GodotLib.getGlobal("xr/openxr/enabled").toBoolean())
if (openxrEnabled && isNativeXRDevice(applicationContext)) {
XR_RUN_GAME_INFO
} else {
RUN_GAME_INFO
}
}
}

protected open fun getEditorWindowInfoForInstanceId(instanceId: Int): EditorWindowInfo? {
private fun getEditorWindowInfoForInstanceId(instanceId: Int): EditorWindowInfo? {
return when (instanceId) {
RUN_GAME_INFO.windowId -> RUN_GAME_INFO
EDITOR_MAIN_INFO.windowId -> EDITOR_MAIN_INFO
XR_RUN_GAME_INFO.windowId -> XR_RUN_GAME_INFO
else -> null
}
}
Expand Down Expand Up @@ -417,8 +452,8 @@ abstract class BaseGodotEditor : GodotActivity() {

return when (policy) {
LaunchPolicy.AUTO -> {
if (isHorizonOSDevice()) {
// Horizon OS UX is more desktop-like and has support for launching adjacent
if (isNativeXRDevice(applicationContext)) {
// Native XR devices are more desktop-like and have support for launching adjacent
// windows. So we always want to launch in adjacent mode when auto is selected.
LaunchPolicy.ADJACENT
} else {
Expand Down Expand Up @@ -450,12 +485,6 @@ abstract class BaseGodotEditor : GodotActivity() {
* Returns true the if the device supports picture-in-picture (PiP)
*/
protected open fun hasPiPSystemFeature(): Boolean {
if (isNativeXRDevice()) {
// Known native XR devices do not support PiP.
// Will need to revisit as they update their OS.
return false
}

return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
}
Expand Down Expand Up @@ -534,15 +563,15 @@ abstract class BaseGodotEditor : GodotActivity() {

override fun supportsFeature(featureTag: String): Boolean {
if (featureTag == "xr_editor") {
return isNativeXRDevice()
return isNativeXRDevice(applicationContext)
}

if (featureTag == "horizonos") {
return isHorizonOSDevice()
return BuildConfig.FLAVOR == "horizonos"
}

if (featureTag == "picoos") {
return isPicoOSDevice()
return BuildConfig.FLAVOR == "picoos"
}

return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ open class GodotXRGame: GodotGame() {
override fun getProjectPermissionsToEnable(): MutableList<String> {
val permissionsToEnable = super.getProjectPermissionsToEnable()

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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="editor_default_window_height">640dp</dimen>
<dimen name="editor_default_window_height">720dp</dimen>
<dimen name="editor_default_window_width">1024dp</dimen>
</resources>
9 changes: 1 addition & 8 deletions platform/android/java/editor/src/picoos/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,8 @@

<activity
android:name=".GodotXRGame"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
android:process=":GodotXRGame"
android:launchMode="singleTask"
android:icon="@mipmap/ic_play_window"
android:label="@string/godot_game_activity_name"
android:exported="false"
android:screenOrientation="landscape"
android:resizeableActivity="false"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
tools:node="merge">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,53 +30,9 @@

package org.godotengine.editor

import org.godotengine.godot.GodotLib
import org.godotengine.godot.utils.isNativeXRDevice

/**
* Primary window of the Godot Editor.
*
* This is the implementation of the editor used when running on PicoOS devices.
*/
open class GodotEditor : BaseGodotEditor() {

companion object {
private val TAG = GodotEditor::class.java.simpleName

internal val XR_RUN_GAME_INFO = EditorWindowInfo(GodotXRGame::class.java, 1667, ":GodotXRGame")
}

override fun retrieveEditorWindowInfo(args: Array<String>): EditorWindowInfo {
var hasEditor = false
var xrModeOn = false

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)
}
}
}

return if (hasEditor) {
EDITOR_MAIN_INFO
} else {
val openxrEnabled = GodotLib.getGlobal("xr/openxr/enabled").toBoolean()
if (openxrEnabled && isNativeXRDevice()) {
XR_RUN_GAME_INFO
} else {
RUN_GAME_INFO
}
}
}

override fun getEditorWindowInfoForInstanceId(instanceId: Int): EditorWindowInfo? {
return when (instanceId) {
XR_RUN_GAME_INFO.windowId -> XR_RUN_GAME_INFO
else -> super.getEditorWindowInfoForInstanceId(instanceId)
}
}
}
open class GodotEditor : BaseGodotEditor()
Loading

0 comments on commit 041cb20

Please sign in to comment.