You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-08 12:40:44 +00:00
Improve support for XR projects
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
/**************************************************************************/
|
||||
/* GodotEditor.kt */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
package org.godotengine.editor
|
||||
|
||||
/**
|
||||
* Primary window of the Godot Editor.
|
||||
*
|
||||
* This is the implementation of the editor used when running on regular Android devices.
|
||||
*/
|
||||
open class GodotEditor : BaseGodotEditor() {
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**************************************************************************/
|
||||
/* GodotEditor.kt */
|
||||
/* BaseGodotEditor.kt */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
@@ -52,6 +52,8 @@ 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.isNativeXRDevice
|
||||
import java.util.*
|
||||
import kotlin.math.min
|
||||
|
||||
@@ -61,13 +63,11 @@ import kotlin.math.min
|
||||
* This provides the basic templates for the activities making up this application.
|
||||
* Each derived activity runs in its own process, which enable up to have several instances of
|
||||
* the Godot engine up and running at the same time.
|
||||
*
|
||||
* It also plays the role of the primary editor window.
|
||||
*/
|
||||
open class GodotEditor : GodotActivity() {
|
||||
abstract class BaseGodotEditor : GodotActivity() {
|
||||
|
||||
companion object {
|
||||
private val TAG = GodotEditor::class.java.simpleName
|
||||
private val TAG = BaseGodotEditor::class.java.simpleName
|
||||
|
||||
private const val WAIT_FOR_DEBUGGER = false
|
||||
|
||||
@@ -81,12 +81,13 @@ open class GodotEditor : GodotActivity() {
|
||||
// Command line arguments
|
||||
private const val FULLSCREEN_ARG = "--fullscreen"
|
||||
private const val FULLSCREEN_ARG_SHORT = "-f"
|
||||
private const val EDITOR_ARG = "--editor"
|
||||
private const val EDITOR_ARG_SHORT = "-e"
|
||||
private const val EDITOR_PROJECT_MANAGER_ARG = "--project-manager"
|
||||
private const val EDITOR_PROJECT_MANAGER_ARG_SHORT = "-p"
|
||||
private const val BREAKPOINTS_ARG = "--breakpoints"
|
||||
private const val BREAKPOINTS_ARG_SHORT = "-b"
|
||||
internal const val EDITOR_ARG = "--editor"
|
||||
internal const val EDITOR_ARG_SHORT = "-e"
|
||||
internal const val EDITOR_PROJECT_MANAGER_ARG = "--project-manager"
|
||||
internal const val EDITOR_PROJECT_MANAGER_ARG_SHORT = "-p"
|
||||
internal const val BREAKPOINTS_ARG = "--breakpoints"
|
||||
internal const val BREAKPOINTS_ARG_SHORT = "-b"
|
||||
internal const val XR_MODE_ARG = "--xr-mode"
|
||||
|
||||
// Info for the various classes used by the editor
|
||||
internal val EDITOR_MAIN_INFO = EditorWindowInfo(GodotEditor::class.java, 777, "")
|
||||
@@ -122,6 +123,20 @@ open class GodotEditor : GodotActivity() {
|
||||
|
||||
internal open fun getEditorWindowInfo() = EDITOR_MAIN_INFO
|
||||
|
||||
/**
|
||||
* Set of permissions to be excluded when requesting all permissions at startup.
|
||||
*
|
||||
* The permissions in this set will be requested on demand based on use cases.
|
||||
*/
|
||||
@CallSuper
|
||||
protected open fun getExcludedPermissions(): MutableSet<String> {
|
||||
return mutableSetOf(
|
||||
// The RECORD_AUDIO permission is requested when the "audio/driver/enable_input" project
|
||||
// setting is enabled.
|
||||
Manifest.permission.RECORD_AUDIO
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
installSplashScreen()
|
||||
|
||||
@@ -131,8 +146,8 @@ open class GodotEditor : GodotActivity() {
|
||||
}
|
||||
|
||||
// We exclude certain permissions from the set we request at startup, as they'll be
|
||||
// requested on demand based on use-cases.
|
||||
PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO))
|
||||
// requested on demand based on use cases.
|
||||
PermissionsUtil.requestManifestPermissions(this, getExcludedPermissions())
|
||||
|
||||
val params = intent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS)
|
||||
Log.d(TAG, "Starting intent $intent with parameters ${params.contentToString()}")
|
||||
@@ -152,8 +167,6 @@ open class GodotEditor : GodotActivity() {
|
||||
val longPressEnabled = enableLongPressGestures()
|
||||
val panScaleEnabled = enablePanAndScaleGestures()
|
||||
|
||||
checkForProjectPermissionsToEnable()
|
||||
|
||||
runOnUiThread {
|
||||
// Enable long press, panning and scaling gestures
|
||||
godotFragment?.godot?.renderView?.inputHandler?.apply {
|
||||
@@ -171,17 +184,6 @@ open class GodotEditor : GodotActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for project permissions to enable
|
||||
*/
|
||||
protected open fun checkForProjectPermissionsToEnable() {
|
||||
// Check for RECORD_AUDIO permission
|
||||
val audioInputEnabled = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("audio/driver/enable_input"))
|
||||
if (audioInputEnabled) {
|
||||
PermissionsUtil.requestPermission(Manifest.permission.RECORD_AUDIO, this)
|
||||
}
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
protected open fun updateCommandLineParams(args: List<String>) {
|
||||
// Update the list of command line params with the new args
|
||||
@@ -196,7 +198,7 @@ open class GodotEditor : GodotActivity() {
|
||||
|
||||
final override fun getCommandLine() = commandLineParams
|
||||
|
||||
protected open fun getEditorWindowInfo(args: Array<String>): EditorWindowInfo {
|
||||
protected open fun retrieveEditorWindowInfo(args: Array<String>): EditorWindowInfo {
|
||||
var hasEditor = false
|
||||
|
||||
var i = 0
|
||||
@@ -273,7 +275,7 @@ open class GodotEditor : GodotActivity() {
|
||||
}
|
||||
|
||||
override fun onNewGodotInstanceRequested(args: Array<String>): Int {
|
||||
val editorWindowInfo = getEditorWindowInfo(args)
|
||||
val editorWindowInfo = retrieveEditorWindowInfo(args)
|
||||
|
||||
// Launch a new activity
|
||||
val sourceView = godotFragment?.view
|
||||
@@ -405,20 +407,26 @@ open class GodotEditor : GodotActivity() {
|
||||
|
||||
return when (policy) {
|
||||
LaunchPolicy.AUTO -> {
|
||||
try {
|
||||
when (Integer.parseInt(GodotLib.getEditorSetting("run/window_placement/android_window"))) {
|
||||
ANDROID_WINDOW_SAME_AS_EDITOR -> LaunchPolicy.SAME
|
||||
ANDROID_WINDOW_SIDE_BY_SIDE_WITH_EDITOR -> LaunchPolicy.ADJACENT
|
||||
ANDROID_WINDOW_SAME_AS_EDITOR_AND_LAUNCH_IN_PIP_MODE -> LaunchPolicy.SAME_AND_LAUNCH_IN_PIP_MODE
|
||||
else -> {
|
||||
// ANDROID_WINDOW_AUTO
|
||||
defaultLaunchPolicy
|
||||
if (isHorizonOSDevice()) {
|
||||
// Horizon OS UX is more desktop-like and has support for launching adjacent
|
||||
// windows. So we always want to launch in adjacent mode when auto is selected.
|
||||
LaunchPolicy.ADJACENT
|
||||
} else {
|
||||
try {
|
||||
when (Integer.parseInt(GodotLib.getEditorSetting("run/window_placement/android_window"))) {
|
||||
ANDROID_WINDOW_SAME_AS_EDITOR -> LaunchPolicy.SAME
|
||||
ANDROID_WINDOW_SIDE_BY_SIDE_WITH_EDITOR -> LaunchPolicy.ADJACENT
|
||||
ANDROID_WINDOW_SAME_AS_EDITOR_AND_LAUNCH_IN_PIP_MODE -> LaunchPolicy.SAME_AND_LAUNCH_IN_PIP_MODE
|
||||
else -> {
|
||||
// ANDROID_WINDOW_AUTO
|
||||
defaultLaunchPolicy
|
||||
}
|
||||
}
|
||||
} catch (e: NumberFormatException) {
|
||||
Log.w(TAG, "Error parsing the Android window placement editor setting", e)
|
||||
// Fall-back to the default launch policy
|
||||
defaultLaunchPolicy
|
||||
}
|
||||
} catch (e: NumberFormatException) {
|
||||
Log.w(TAG, "Error parsing the Android window placement editor setting", e)
|
||||
// Fall-back to the default launch policy
|
||||
defaultLaunchPolicy
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,8 +439,16 @@ open class GodotEditor : GodotActivity() {
|
||||
/**
|
||||
* Returns true the if the device supports picture-in-picture (PiP)
|
||||
*/
|
||||
protected open fun hasPiPSystemFeature() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
|
||||
packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
|
||||
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)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
@@ -42,9 +42,9 @@ import android.util.Log
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
* Used by the [GodotEditor] classes to dispatch messages across processes.
|
||||
* Used by the [BaseGodotEditor] classes to dispatch messages across processes.
|
||||
*/
|
||||
internal class EditorMessageDispatcher(private val editor: GodotEditor) {
|
||||
internal class EditorMessageDispatcher(private val editor: BaseGodotEditor) {
|
||||
|
||||
companion object {
|
||||
private val TAG = EditorMessageDispatcher::class.java.simpleName
|
||||
@@ -173,7 +173,11 @@ internal class EditorMessageDispatcher(private val editor: GodotEditor) {
|
||||
// to the sender.
|
||||
val senderId = messengerBundle.getInt(KEY_EDITOR_ID)
|
||||
val senderMessenger: Messenger? = messengerBundle.getParcelable(KEY_EDITOR_MESSENGER)
|
||||
registerMessenger(senderId, senderMessenger)
|
||||
registerMessenger(senderId, senderMessenger) {
|
||||
// Terminate current instance when parent is no longer available.
|
||||
Log.d(TAG, "Terminating current editor instance because parent is no longer available")
|
||||
editor.finish()
|
||||
}
|
||||
|
||||
// Register ourselves to the sender so that it can communicate with us.
|
||||
registerSelfTo(pm, senderMessenger, editor.getEditorWindowInfo().windowId)
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
package org.godotengine.editor
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.PictureInPictureParams
|
||||
import android.content.Intent
|
||||
@@ -38,12 +39,15 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.annotation.CallSuper
|
||||
import org.godotengine.godot.GodotLib
|
||||
import org.godotengine.godot.utils.PermissionsUtil
|
||||
import org.godotengine.godot.utils.ProcessPhoenix
|
||||
|
||||
/**
|
||||
* Drives the 'run project' window of the Godot Editor.
|
||||
*/
|
||||
class GodotGame : GodotEditor() {
|
||||
open class GodotGame : GodotEditor() {
|
||||
|
||||
companion object {
|
||||
private val TAG = GodotGame::class.java.simpleName
|
||||
@@ -136,8 +140,53 @@ class GodotGame : GodotEditor() {
|
||||
|
||||
override fun enablePanAndScaleGestures() = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/pointing/android/enable_pan_and_scale_gestures"))
|
||||
|
||||
override fun checkForProjectPermissionsToEnable() {
|
||||
// Nothing to do.. by the time we get here, the project permissions will have already
|
||||
// been requested by the Editor window.
|
||||
override fun onGodotSetupCompleted() {
|
||||
super.onGodotSetupCompleted()
|
||||
Log.v(TAG, "OnGodotSetupCompleted")
|
||||
|
||||
// Check if we should be running in XR instead (if available) as it's possible we were
|
||||
// launched from the project manager which doesn't have that information.
|
||||
val launchingArgs = intent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS)
|
||||
if (launchingArgs != null) {
|
||||
val editorWindowInfo = retrieveEditorWindowInfo(launchingArgs)
|
||||
if (editorWindowInfo != getEditorWindowInfo()) {
|
||||
val relaunchIntent = getNewGodotInstanceIntent(editorWindowInfo, launchingArgs)
|
||||
relaunchIntent.putExtra(EXTRA_NEW_LAUNCH, true)
|
||||
.putExtra(EditorMessageDispatcher.EXTRA_MSG_DISPATCHER_PAYLOAD, intent.getBundleExtra(EditorMessageDispatcher.EXTRA_MSG_DISPATCHER_PAYLOAD))
|
||||
|
||||
Log.d(TAG, "Relaunching XR project using ${editorWindowInfo.windowClassName} with parameters ${launchingArgs.contentToString()}")
|
||||
val godot = godot
|
||||
if (godot != null) {
|
||||
godot.destroyAndKillProcess {
|
||||
ProcessPhoenix.triggerRebirth(this, relaunchIntent)
|
||||
}
|
||||
} else {
|
||||
ProcessPhoenix.triggerRebirth(this, relaunchIntent)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Request project runtime permissions if necessary
|
||||
val permissionsToEnable = getProjectPermissionsToEnable()
|
||||
if (permissionsToEnable.isNotEmpty()) {
|
||||
PermissionsUtil.requestPermissions(this, permissionsToEnable)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for project permissions to enable
|
||||
*/
|
||||
@CallSuper
|
||||
protected open fun getProjectPermissionsToEnable(): MutableList<String> {
|
||||
val permissionsToEnable = mutableListOf<String>()
|
||||
|
||||
// Check for RECORD_AUDIO permission
|
||||
val audioInputEnabled = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("audio/driver/enable_input"))
|
||||
if (audioInputEnabled) {
|
||||
permissionsToEnable.add(Manifest.permission.RECORD_AUDIO)
|
||||
}
|
||||
|
||||
return permissionsToEnable
|
||||
}
|
||||
}
|
||||
|
||||
99
platform/android/java/editor/src/meta/AndroidManifest.xml
Normal file
99
platform/android/java/editor/src/meta/AndroidManifest.xml
Normal file
@@ -0,0 +1,99 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:horizonos="http://schemas.horizonos/sdk">
|
||||
|
||||
<horizonos:uses-horizonos-sdk
|
||||
horizonos:minSdkVersion="69"
|
||||
horizonos:targetSdkVersion="69" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.vr.headtracking"
|
||||
android:required="true"
|
||||
android:version="1"/>
|
||||
|
||||
<!-- Oculus Quest hand tracking -->
|
||||
<uses-permission android:name="com.oculus.permission.HAND_TRACKING" />
|
||||
<uses-feature
|
||||
android:name="oculus.software.handtracking"
|
||||
android:required="false" />
|
||||
|
||||
<!-- Passthrough feature flag -->
|
||||
<uses-feature android:name="com.oculus.feature.PASSTHROUGH"
|
||||
android:required="false" />
|
||||
|
||||
<!-- Overlay keyboard support -->
|
||||
<uses-feature android:name="oculus.software.overlay_keyboard" android:required="false"/>
|
||||
|
||||
<!-- Render model -->
|
||||
<uses-permission android:name="com.oculus.permission.RENDER_MODEL" />
|
||||
<uses-feature android:name="com.oculus.feature.RENDER_MODEL" android:required="false" />
|
||||
|
||||
<!-- Anchor api -->
|
||||
<uses-permission android:name="com.oculus.permission.USE_ANCHOR_API" />
|
||||
|
||||
<!-- Scene api -->
|
||||
<uses-permission android:name="com.oculus.permission.USE_SCENE" />
|
||||
|
||||
<application>
|
||||
|
||||
<activity
|
||||
android:name=".GodotEditor"
|
||||
android:exported="true"
|
||||
android:screenOrientation="landscape"
|
||||
tools:node="merge"
|
||||
tools:replace="android:screenOrientation">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="com.oculus.intent.category.2D" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data android:name="com.oculus.vrshell.free_resizing_lock_aspect_ratio" android:value="true"/>
|
||||
</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">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="com.oculus.intent.category.VR" />
|
||||
<category android:name="org.khronos.openxr.intent.category.IMMERSIVE_HMD" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- Supported Meta devices -->
|
||||
<meta-data
|
||||
android:name="com.oculus.supportedDevices"
|
||||
android:value="quest3|questpro"
|
||||
tools:replace="android:value" />
|
||||
|
||||
<!--
|
||||
We remove this meta-data originating from the vendors plugin as we only need the loader for
|
||||
now since the project being edited provides its own version of the vendors plugin.
|
||||
|
||||
This needs to be removed once we start implementing the immersive version of the project
|
||||
manager and editor windows.
|
||||
-->
|
||||
<meta-data
|
||||
android:name="org.godotengine.plugin.v2.GodotOpenXRMeta"
|
||||
android:value="org.godotengine.openxr.vendors.meta.GodotOpenXRMeta"
|
||||
tools:node="remove" />
|
||||
|
||||
<!-- Enable system splash screen -->
|
||||
<meta-data android:name="com.oculus.ossplash" android:value="true"/>
|
||||
<!-- Enable passthrough background during the splash screen -->
|
||||
<meta-data android:name="com.oculus.ossplash.background" android:value="passthrough-contextual"/>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
BIN
platform/android/java/editor/src/meta/assets/vr_splash.png
Normal file
BIN
platform/android/java/editor/src/meta/assets/vr_splash.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,94 @@
|
||||
/**************************************************************************/
|
||||
/* GodotEditor.kt */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
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 Meta 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")
|
||||
|
||||
internal const val USE_ANCHOR_API_PERMISSION = "com.oculus.permission.USE_ANCHOR_API"
|
||||
internal const val USE_SCENE_PERMISSION = "com.oculus.permission.USE_SCENE"
|
||||
}
|
||||
|
||||
override fun getExcludedPermissions(): MutableSet<String> {
|
||||
val excludedPermissions = super.getExcludedPermissions()
|
||||
// The USE_ANCHOR_API and USE_SCENE permissions are requested when the "xr/openxr/enabled"
|
||||
// project setting is enabled.
|
||||
excludedPermissions.add(USE_ANCHOR_API_PERMISSION)
|
||||
excludedPermissions.add(USE_SCENE_PERMISSION)
|
||||
return excludedPermissions
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*************************************************************************/
|
||||
/* GodotXRGame.kt */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
package org.godotengine.editor
|
||||
|
||||
import org.godotengine.godot.GodotLib
|
||||
import org.godotengine.godot.utils.PermissionsUtil
|
||||
import org.godotengine.godot.xr.XRMode
|
||||
|
||||
/**
|
||||
* Provide support for running XR apps / games from the editor window.
|
||||
*/
|
||||
open class GodotXRGame: GodotGame() {
|
||||
|
||||
override fun overrideOrientationRequest() = true
|
||||
|
||||
override fun updateCommandLineParams(args: List<String>) {
|
||||
val updatedArgs = ArrayList<String>()
|
||||
if (!args.contains(XRMode.OPENXR.cmdLineArg)) {
|
||||
updatedArgs.add(XRMode.OPENXR.cmdLineArg)
|
||||
}
|
||||
if (!args.contains(XR_MODE_ARG)) {
|
||||
updatedArgs.add(XR_MODE_ARG)
|
||||
updatedArgs.add("on")
|
||||
}
|
||||
updatedArgs.addAll(args)
|
||||
|
||||
super.updateCommandLineParams(updatedArgs)
|
||||
}
|
||||
|
||||
override fun getEditorWindowInfo() = XR_RUN_GAME_INFO
|
||||
|
||||
override fun getProjectPermissionsToEnable(): MutableList<String> {
|
||||
val permissionsToEnable = super.getProjectPermissionsToEnable()
|
||||
|
||||
val openxrEnabled = GodotLib.getGlobal("xr/openxr/enabled").toBoolean()
|
||||
if (openxrEnabled) {
|
||||
permissionsToEnable.add(USE_ANCHOR_API_PERMISSION)
|
||||
permissionsToEnable.add(USE_SCENE_PERMISSION)
|
||||
}
|
||||
|
||||
return permissionsToEnable
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user