Skip to content

Commit

Permalink
Configuring the VR Editor for standalone devices
Browse files Browse the repository at this point in the history
  • Loading branch information
m4gr3d committed Jan 9, 2023
1 parent 98ace5b commit a2c64b3
Show file tree
Hide file tree
Showing 9 changed files with 375 additions and 25 deletions.
11 changes: 7 additions & 4 deletions platform/android/display_server_android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -662,16 +662,19 @@ void DisplayServerAndroid::cursor_set_custom_image(const Ref<Resource> &p_cursor

void DisplayServerAndroid::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
#if defined(VULKAN_ENABLED)
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
if (rendering_driver == "vulkan") {
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
}
#endif
}

DisplayServer::VSyncMode DisplayServerAndroid::window_get_vsync_mode(WindowID p_window) const {
#if defined(VULKAN_ENABLED)
return context_vulkan->get_vsync_mode(p_window);
#else
return DisplayServer::VSYNC_ENABLED;
if (rendering_driver == "vulkan") {
return context_vulkan->get_vsync_mode(p_window);
}
#endif
return DisplayServer::VSYNC_ENABLED;
}

void DisplayServerAndroid::reset_swap_buffers_flag() {
Expand Down
96 changes: 84 additions & 12 deletions platform/android/java/editor/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,6 @@ plugins {
id 'org.jetbrains.kotlin.android'
}

dependencies {
implementation libraries.kotlinStdLib
implementation libraries.androidxFragment
implementation project(":lib")

implementation "androidx.window:window:1.0.0"
}

ext {
// Build number added as a suffix to the version code, and incremented for each build/upload to
// the Google Play store.
Expand Down Expand Up @@ -76,26 +68,106 @@ android {
}
}

flavorDimensions "xrMode", "xrRuntime"
productFlavors {
pancake {
dimension "xrMode"
}
openxr {
dimension "xrMode"
ndk {
abiFilters "arm64-v8a"
}
applicationIdSuffix ".openxr"
versionNameSuffix "-openxr"
}

google {
dimension "xrRuntime"
}
meta {
dimension "xrRuntime"
applicationIdSuffix ".meta"
versionNameSuffix "-meta"
}
pico {
dimension "xrRuntime"
applicationIdSuffix ".pico"
versionNameSuffix "-pico"
}
}

packagingOptions {
// 'doNotStrip' is enabled for development within Android Studio
if (shouldNotStrip()) {
doNotStrip '**/*.so'
}
}

// Disable 'release' buildtype.
// The editor can't be used with target=release only, as debugging tools are then not
// included, and it would crash on errors instead of reporting them.
variantFilter { variant ->
// Disable 'release' buildtype.
// The editor can't be used with target=release only, as debugging tools are then not
// included, and it would crash on errors instead of reporting them.
if (variant.buildType.name == "release") {
setIgnore(true)
}

// Disable invalid flavors combinations
def names = variant.flavors*.name
if (names.contains("pancake")) {
if (names.contains("meta") || names.contains("pico")) {
setIgnore(true)
}
}
if (names.contains("openxr") && names.contains("google")) {
setIgnore(true)
}
}

applicationVariants.all { variant ->
variant.outputs.all { output ->
def suffix = variant.name == "dev" ? "_dev" : ""
def suffix = ""
switch (variant.name) {
case "openxrMetaDev":
suffix = "_openxr_meta_dev"
break
case "openxrMetaDebug":
suffix = "_openxr_meta"
break
case "openxrPicoDev":
suffix = "_openxr_pico_dev"
break
case "openxrPicoDebug":
suffix = "_openxr_pico"
break
case "pancakeGoogleDev":
suffix = "_dev"
break
case "pancakeGoogleDebug":
default:
suffix = ""
break
}
output.outputFileName = "android_editor${suffix}.apk"
}
}
}

configurations {
openxrMetaImplementation {}
openxrPicoImplementation {}
}

dependencies {
implementation libraries.kotlinStdLib
implementation libraries.androidxFragment
implementation project(":lib")

implementation "androidx.window:window:1.0.0"

// Meta OpenXR dependencies
openxrMetaImplementation "org.godotengine:godot-openxr-loaders-meta:1.0.0"

// Pico OpenXR dependencies
openxrPicoImplementation "org.godotengine:godot-openxr-loaders-pico:1.0.0"
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import android.os.Debug
import android.os.Environment
import android.util.Log
import android.widget.Toast
import androidx.annotation.CallSuper
import androidx.window.layout.WindowMetricsCalculator
import org.godotengine.godot.FullScreenGodotApp
import org.godotengine.godot.utils.PermissionsUtil
Expand All @@ -64,11 +65,11 @@ open class GodotEditor : FullScreenGodotApp() {

private const val COMMAND_LINE_PARAMS = "command_line_params"

private const val EDITOR_ARG = "--editor"
private const val EDITOR_ARG_SHORT = "-e"
const val EDITOR_ARG = "--editor"
const val EDITOR_ARG_SHORT = "-e"

private const val PROJECT_MANAGER_ARG = "--project-manager"
private const val PROJECT_MANAGER_ARG_SHORT = "-p"
const val PROJECT_MANAGER_ARG = "--project-manager"
const val PROJECT_MANAGER_ARG_SHORT = "-p"
}

private val commandLineParams = ArrayList<String>()
Expand All @@ -92,39 +93,61 @@ open class GodotEditor : FullScreenGodotApp() {
}
}

private fun updateCommandLineParams(args: Array<String>?) {
@CallSuper
protected open fun updateCommandLineParams(args: Array<String>?) {
// Update the list of command line params with the new args
commandLineParams.clear()
if (args != null && args.isNotEmpty()) {
commandLineParams.addAll(listOf(*args))
}
}

override fun getCommandLine() = commandLineParams
final override fun getCommandLine() = commandLineParams

override fun onNewGodotInstanceRequested(args: Array<String>) {
open fun selectGodotInstanceTargetClass(args: Array<String>): Class<*> {
// Parse the arguments to figure out which activity to start.
var targetClass: Class<*> = GodotGame::class.java

for (arg in args) {
if (EDITOR_ARG == arg || EDITOR_ARG_SHORT == arg) {
targetClass = GodotEditor::class.java
break
}

if (PROJECT_MANAGER_ARG == arg || PROJECT_MANAGER_ARG_SHORT == arg) {
targetClass = GodotProjectManager::class.java
break
}
}

return targetClass
}

open fun shouldLaunchGodotInstanceAdjacent(args: Array<String>): Boolean {
// Whether we should launch the new godot instance in an adjacent window
// https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_LAUNCH_ADJACENT
var launchAdjacent =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && (isInMultiWindowMode || isLargeScreen)

for (arg in args) {
if (EDITOR_ARG == arg || EDITOR_ARG_SHORT == arg) {
targetClass = GodotEditor::class.java
launchAdjacent = false
break
}

if (PROJECT_MANAGER_ARG == arg || PROJECT_MANAGER_ARG_SHORT == arg) {
targetClass = GodotProjectManager::class.java
launchAdjacent = false
break
}
}

return launchAdjacent
}

final override fun onNewGodotInstanceRequested(args: Array<String>) {
val launchAdjacent = shouldLaunchGodotInstanceAdjacent(args)
val targetClass = selectGodotInstanceTargetClass(args)

// Launch a new activity
val newInstance = Intent(this, targetClass)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
Expand Down
53 changes: 53 additions & 0 deletions platform/android/java/editor/src/openxr/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.godotengine.editor">

<application>

<activity android:name=".GodotXRProjectManager"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
android:process=":GodotXRProjectManager"
android:launchMode="singleTask"
android:exported="true"
android:screenOrientation="userLandscape"
android:resizeableActivity="false"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">

<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.oculus.intent.category.VR" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity
android:name=".GodotXREditor"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
android:process=":GodotXREditor"
android:launchMode="singleTask"
android:exported="false"
android:screenOrientation="userLandscape"
android:resizeableActivity="false"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
<intent-filter>
<category android:name="com.oculus.intent.category.VR" />
</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:exported="false"
android:screenOrientation="userLandscape"
android:resizeableActivity="false"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
<intent-filter>
<category android:name="com.oculus.intent.category.VR" />
</intent-filter>
</activity>

</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*************************************************************************/
/* GodotXREditor.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.xr.XRMode

/**
* Base class for the Godot Android XR Editor activities.
*/
open class GodotXREditor: GodotEditor() {
override fun updateCommandLineParams(args: Array<String>?) {
val updatedArgs = Array((args?.size?:0) + 3) {
if (it == 0) {
"--xr-mode"
} else if (it == 1) {
"on"
}else if (it == 2) {
XRMode.OPENXR.cmdLineArg
} else {
args?.get(it -3) ?: ""
}
}

super.updateCommandLineParams(updatedArgs)
}

override fun shouldLaunchGodotInstanceAdjacent(args: Array<String>): Boolean {
return false
}

override fun selectGodotInstanceTargetClass(args: Array<String>): Class<*> {
// Parse the arguments to figure out which activity to start.
var targetClass: Class<*> = GodotXRGame::class.java

for (arg in args) {
if (EDITOR_ARG == arg || EDITOR_ARG_SHORT == arg) {
targetClass = GodotXREditor::class.java
break
}

if (PROJECT_MANAGER_ARG == arg || PROJECT_MANAGER_ARG_SHORT == arg) {
targetClass = GodotXRProjectManager::class.java
break
}
}

return targetClass
}
}
Loading

0 comments on commit a2c64b3

Please sign in to comment.