|
@@ -60,14 +60,19 @@ 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.editor.utils.EditorUtils
|
|
|
+import org.godotengine.godot.editor.utils.GameMenuUtils
|
|
|
+import org.godotengine.godot.editor.utils.GameMenuUtils.GameEmbedMode
|
|
|
+import org.godotengine.godot.editor.utils.GameMenuUtils.fetchGameEmbedMode
|
|
|
import org.godotengine.godot.error.Error
|
|
|
import org.godotengine.godot.utils.DialogUtils
|
|
|
-import org.godotengine.godot.utils.GameMenuUtils
|
|
|
-import org.godotengine.godot.utils.GameMenuUtils.GameEmbedMode
|
|
|
-import org.godotengine.godot.utils.GameMenuUtils.fetchGameEmbedMode
|
|
|
import org.godotengine.godot.utils.PermissionsUtil
|
|
|
import org.godotengine.godot.utils.ProcessPhoenix
|
|
|
import org.godotengine.godot.utils.isNativeXRDevice
|
|
|
+import org.godotengine.godot.xr.HybridMode
|
|
|
+import org.godotengine.godot.xr.getHybridAppLaunchMode
|
|
|
+import org.godotengine.godot.xr.HYBRID_APP_PANEL_CATEGORY
|
|
|
+import org.godotengine.godot.xr.HYBRID_APP_IMMERSIVE_CATEGORY
|
|
|
import kotlin.math.min
|
|
|
|
|
|
/**
|
|
@@ -98,6 +103,8 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|
|
private const val EDITOR_PROJECT_MANAGER_ARG = "--project-manager"
|
|
|
private const val EDITOR_PROJECT_MANAGER_ARG_SHORT = "-p"
|
|
|
internal const val XR_MODE_ARG = "--xr-mode"
|
|
|
+ private const val SCENE_ARG = "--scene"
|
|
|
+ private const val PATH_ARG = "--path"
|
|
|
|
|
|
// Info for the various classes used by the editor.
|
|
|
internal val EDITOR_MAIN_INFO = EditorWindowInfo(GodotEditor::class.java, 777, "")
|
|
@@ -236,6 +243,50 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|
|
setupGameMenuBar()
|
|
|
}
|
|
|
|
|
|
+ override fun onNewIntent(newIntent: Intent) {
|
|
|
+ if (newIntent.hasCategory(HYBRID_APP_PANEL_CATEGORY) || newIntent.hasCategory(HYBRID_APP_IMMERSIVE_CATEGORY)) {
|
|
|
+ val params = newIntent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS)
|
|
|
+ Log.d(TAG, "Received hybrid transition intent $newIntent with parameters ${params.contentToString()}")
|
|
|
+ // Override EXTRA_NEW_LAUNCH so the editor is not restarted
|
|
|
+ newIntent.putExtra(EXTRA_NEW_LAUNCH, false)
|
|
|
+
|
|
|
+ godot?.runOnRenderThread {
|
|
|
+ // Look for the scene and xr-mode arguments
|
|
|
+ var scene = ""
|
|
|
+ var xrMode = XR_MODE_DEFAULT
|
|
|
+ var path = ""
|
|
|
+ if (params != null) {
|
|
|
+ val sceneIndex = params.indexOf(SCENE_ARG)
|
|
|
+ if (sceneIndex != -1 && sceneIndex + 1 < params.size) {
|
|
|
+ scene = params[sceneIndex +1]
|
|
|
+ }
|
|
|
+
|
|
|
+ val xrModeIndex = params.indexOf(XR_MODE_ARG)
|
|
|
+ if (xrModeIndex != -1 && xrModeIndex + 1 < params.size) {
|
|
|
+ xrMode = params[xrModeIndex + 1]
|
|
|
+ }
|
|
|
+
|
|
|
+ val pathIndex = params.indexOf(PATH_ARG)
|
|
|
+ if (pathIndex != -1 && pathIndex + 1 < params.size) {
|
|
|
+ path = params[pathIndex + 1]
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ val sceneArgs = mutableSetOf(XR_MODE_ARG, xrMode).apply {
|
|
|
+ if (path.isNotEmpty() && scene.isEmpty()) {
|
|
|
+ add(PATH_ARG)
|
|
|
+ add(path)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Log.d(TAG, "Running scene $scene with arguments: $sceneArgs")
|
|
|
+ EditorUtils.runScene(scene, sceneArgs.toTypedArray())
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ super.onNewIntent(newIntent)
|
|
|
+ }
|
|
|
+
|
|
|
protected open fun shouldShowGameMenuBar() = gameMenuContainer != null
|
|
|
|
|
|
private fun setupGameMenuBar() {
|
|
@@ -327,26 +378,41 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return if (hasEditor) {
|
|
|
- EDITOR_MAIN_INFO
|
|
|
- } else {
|
|
|
- // Launching a game.
|
|
|
- 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 {
|
|
|
- if (godot?.isProjectManagerHint() == true || isNativeXRDevice(applicationContext)) {
|
|
|
+ if (hasEditor) {
|
|
|
+ return EDITOR_MAIN_INFO
|
|
|
+ }
|
|
|
+
|
|
|
+ // Launching a game.
|
|
|
+ if (isNativeXRDevice(applicationContext)) {
|
|
|
+ if (xrMode == XR_MODE_ON) {
|
|
|
+ return XR_RUN_GAME_INFO
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((xrMode == XR_MODE_DEFAULT && GodotLib.getGlobal("xr/openxr/enabled").toBoolean())) {
|
|
|
+ val hybridLaunchMode = getHybridAppLaunchMode()
|
|
|
+
|
|
|
+ return if (hybridLaunchMode == HybridMode.PANEL) {
|
|
|
RUN_GAME_INFO
|
|
|
} else {
|
|
|
- val resolvedEmbedMode = resolveGameEmbedModeIfNeeded(gameEmbedMode)
|
|
|
- if (resolvedEmbedMode == GameEmbedMode.DISABLED) {
|
|
|
- RUN_GAME_INFO
|
|
|
- } else {
|
|
|
- EMBEDDED_RUN_GAME_INFO
|
|
|
- }
|
|
|
+ XR_RUN_GAME_INFO
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // Native XR devices don't support embed mode yet.
|
|
|
+ return RUN_GAME_INFO
|
|
|
+ }
|
|
|
+
|
|
|
+ // Project manager doesn't support embed mode.
|
|
|
+ if (godot?.isProjectManagerHint() == true) {
|
|
|
+ return RUN_GAME_INFO
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check for embed mode launch.
|
|
|
+ val resolvedEmbedMode = resolveGameEmbedModeIfNeeded(gameEmbedMode)
|
|
|
+ return if (resolvedEmbedMode == GameEmbedMode.DISABLED) {
|
|
|
+ RUN_GAME_INFO
|
|
|
+ } else {
|
|
|
+ EMBEDDED_RUN_GAME_INFO
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -626,6 +692,7 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|
|
return verifyApk(godot.fileAccessHandler, apkPath)
|
|
|
}
|
|
|
|
|
|
+ @CallSuper
|
|
|
override fun supportsFeature(featureTag: String): Boolean {
|
|
|
if (featureTag == "xr_editor") {
|
|
|
return isNativeXRDevice(applicationContext)
|
|
@@ -639,11 +706,12 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|
|
return BuildConfig.FLAVOR == "picoos"
|
|
|
}
|
|
|
|
|
|
- return false
|
|
|
+ return super.supportsFeature(featureTag)
|
|
|
}
|
|
|
|
|
|
- internal fun onEditorConnected(connectedEditorId: Int) {
|
|
|
- when (connectedEditorId) {
|
|
|
+ internal fun onEditorConnected(editorId: Int) {
|
|
|
+ Log.d(TAG, "Editor $editorId connected!")
|
|
|
+ when (editorId) {
|
|
|
EMBEDDED_RUN_GAME_INFO.windowId, RUN_GAME_INFO.windowId -> {
|
|
|
runOnUiThread {
|
|
|
embeddedGameViewContainerWindow?.isVisible = false
|
|
@@ -652,12 +720,16 @@ abstract class BaseGodotEditor : GodotActivity(), GameMenuFragment.GameMenuListe
|
|
|
|
|
|
XR_RUN_GAME_INFO.windowId -> {
|
|
|
runOnUiThread {
|
|
|
- updateEmbeddedGameView(true, false)
|
|
|
+ updateEmbeddedGameView(gameRunning = true, gameEmbedded = false)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ internal fun onEditorDisconnected(editorId: Int) {
|
|
|
+ Log.d(TAG, "Editor $editorId disconnected!")
|
|
|
+ }
|
|
|
+
|
|
|
private fun updateEmbeddedGameView(gameRunning: Boolean, gameEmbedded: Boolean) {
|
|
|
if (gameRunning) {
|
|
|
embeddedGameStateLabel?.apply {
|