Browse Source

Enable XR Preview Mode for PICO OS

Supported features in the immersive preview mode
- Passthrough
- Hand tracking
Notes:
- Multi-window is only available for internal apps on PICO OS, therefore launching adjacent windows is not possible currently.
- Passthrough splash screen is not supported on PICO OS
ygz-bd 10 months ago
parent
commit
a2bfb7cff2

+ 1 - 0
.github/workflows/android_builds.yml

@@ -87,6 +87,7 @@ jobs:
           cd platform/android/java
           ./gradlew generateGodotEditor
           ./gradlew generateGodotHorizonOSEditor
+          ./gradlew generateGodotPicoOSEditor
           cd ../../..
           ls -l bin/android_editor_builds/
 

+ 14 - 2
platform/android/java/build.gradle

@@ -25,7 +25,7 @@ allprojects {
 ext {
     supportedAbis = ["arm32", "arm64", "x86_32", "x86_64"]
     supportedFlavors = ["editor", "template"]
-    supportedAndroidDistributions = ["android", "horizonos"]
+    supportedAndroidDistributions = ["android", "horizonos", "picoos"]
     supportedFlavorsBuildTypes = [
         "editor": ["dev", "debug", "release"],
         "template": ["dev", "debug", "release"]
@@ -96,7 +96,7 @@ def templateExcludedBuildTask() {
  * Generates the build tasks for the given flavor
  * @param flavor Must be one of the supported flavors ('template' / 'editor')
  * @param edition Must be one of the supported editions ('standard' / 'mono')
- * @param androidDistro Must be one of the supported Android distributions ('android' / 'horizonos')
+ * @param androidDistro Must be one of the supported Android distributions ('android' / 'horizonos' / 'picoos')
  */
 def generateBuildTasks(String flavor = "template", String edition = "standard", String androidDistro = "android") {
     if (!supportedFlavors.contains(flavor)) {
@@ -237,6 +237,18 @@ task generateGodotHorizonOSEditor {
     dependsOn = generateBuildTasks("editor", "standard", "horizonos")
 }
 
+/**
+ * Generate the Godot Editor binaries for PicoOS devices.
+ *
+ * Note: Unless the 'generateNativeLibs` argument is specified, the Godot 'tools' shared libraries
+ * must have been generated (via scons) prior to running this gradle task.
+ * The task will only build the binaries for which the shared libraries is available.
+ */
+task generateGodotPicoOSEditor {
+    gradle.startParameter.excludedTaskNames += templateExcludedBuildTask()
+    dependsOn = generateBuildTasks("editor", "standard", "picoos")
+}
+
 /**
  * Master task used to coordinate the tasks defined above to generate the set of Godot templates.
  */

+ 14 - 0
platform/android/java/editor/build.gradle

@@ -163,6 +163,18 @@ android {
             minSdkVersion 23
             targetSdkVersion 32
         }
+        picoos {
+            dimension "android_distribution"
+            missingDimensionStrategy 'products', 'editor'
+            ndk {
+                //noinspection ChromeOsAbiSupport
+                abiFilters "arm64-v8a"
+            }
+            applicationIdSuffix ".pico"
+            versionNameSuffix "-pico"
+            minSdkVersion 29
+            targetSdkVersion 32
+        }
     }
 }
 
@@ -177,4 +189,6 @@ dependencies {
 
     // Meta dependencies
     horizonosImplementation "org.godotengine:godot-openxr-vendors-meta:3.0.0-stable"
+    // Pico dependencies
+    picoosImplementation "org.godotengine:godot-openxr-vendors-pico:3.0.1-stable"
 }

+ 5 - 0
platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt

@@ -53,6 +53,7 @@ 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
@@ -521,6 +522,10 @@ abstract class BaseGodotEditor : GodotActivity() {
 			return isHorizonOSDevice()
 		}
 
+		if (featureTag == "picoos") {
+			return isPicoOSDevice()
+		}
+
         return false
     }
 }

+ 83 - 0
platform/android/java/editor/src/picoos/AndroidManifest.xml

@@ -0,0 +1,83 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <uses-feature
+        android:name="android.hardware.vr.headtracking"
+        android:required="true"
+        android:version="1"/>
+
+    <uses-permission
+        android:name="com.pvr.tobactivate.permission.AUTH_CHECK" />
+
+    <uses-permission
+        android:name="com.picovr.permission.HAND_TRACKING" />
+
+    <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" />
+            </intent-filter>
+        </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="org.khronos.openxr.intent.category.IMMERSIVE_HMD" />
+            </intent-filter>
+        </activity>
+
+        <!--
+        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.GodotOpenXRPico"
+            android:value="org.godotengine.openxr.vendors.pico.GodotOpenXRPico"
+            tools:node="remove"/>
+
+        <!-- Enable system splash screen. Passthrough splash screen is not supported yet-->
+        <meta-data
+            android:name="pvr.app.splash"
+            android:value="0" />
+
+        <!-- Enable passthrough-->
+        <meta-data
+            android:name="enable_vst"
+            android:value="1" />
+
+        <!-- PICO hand tracking -->
+        <meta-data
+            android:name="handtracking"
+            android:value="1" />
+
+        <!-- Run as a 2D window app.-->
+        <meta-data
+            android:name="pvr.app.type"
+            android:value="2d"
+            tools:replace="android:value"/>
+
+    </application>
+
+</manifest>

BIN
platform/android/java/editor/src/picoos/assets/vr_splash.png


+ 82 - 0
platform/android/java/editor/src/picoos/java/org/godotengine/editor/GodotEditor.kt

@@ -0,0 +1,82 @@
+/**************************************************************************/
+/*  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 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)
+		}
+	}
+}

+ 59 - 0
platform/android/java/editor/src/picoos/java/org/godotengine/editor/GodotXRGame.kt

@@ -0,0 +1,59 @@
+/*************************************************************************/
+/*  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.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
+
+}

+ 8 - 1
platform/android/java/lib/src/org/godotengine/godot/utils/DeviceUtils.kt

@@ -44,9 +44,16 @@ fun isHorizonOSDevice(): Boolean {
 	return "Oculus".equals(Build.BRAND, true)
 }
 
+/**
+ * Returns true if running on PICO OS.
+ */
+fun isPicoOSDevice(): Boolean {
+	return ("Pico".equals(Build.BRAND, true))
+}
+
 /**
  * Returns true if running on a native Android XR device.
  */
 fun isNativeXRDevice(): Boolean {
-	return isHorizonOSDevice()
+	return isHorizonOSDevice() || isPicoOSDevice()
 }