From 605b97075f9f5990c166ca38b715d2b254c1d10f Mon Sep 17 00:00:00 2001 From: Jamie Pate Date: Thu, 2 Jan 2025 12:44:40 -0800 Subject: [PATCH] Fix create_instance in android GodotApp so non-editor apps can restart Enables OS.create_instance(args) and OS.set_restart_on_exit(true, args) on android. Borrowed the logic from the editor, so it completely restarts the process so you can pass --rendering-method, --rendering-driver to switch between forward_plus, mobile, gl_compatibility etc on an exported app. Related: https://github.com/godotengine/godot-proposals/issues/6423 --- .../org/godotengine/editor/BaseGodotEditor.kt | 34 +++---------- .../org/godotengine/editor/GodotXRGame.kt | 4 +- .../lib/src/org/godotengine/godot/Godot.kt | 23 +++++++-- .../org/godotengine/godot/GodotActivity.kt | 49 +++++++++++++++++++ 4 files changed, 79 insertions(+), 31 deletions(-) diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt index b1fd8a1124dd..45662dbae047 100644 --- a/platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt +++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt @@ -71,8 +71,6 @@ abstract class BaseGodotEditor : GodotActivity() { private const val WAIT_FOR_DEBUGGER = false - @JvmStatic - protected val EXTRA_COMMAND_LINE_PARAMS = "command_line_params" @JvmStatic protected val EXTRA_PIP_AVAILABLE = "pip_available" @JvmStatic @@ -130,7 +128,6 @@ abstract class BaseGodotEditor : GodotActivity() { } private val editorMessageDispatcher = EditorMessageDispatcher(this) - private val commandLineParams = ArrayList() private val editorLoadingIndicator: View? by lazy { findViewById(R.id.editor_loading_indicator) } override fun getGodotAppLayout() = R.layout.godot_editor_layout @@ -183,10 +180,6 @@ abstract class BaseGodotEditor : GodotActivity() { // 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()}") - updateCommandLineParams(params?.asList() ?: emptyList()) - editorMessageDispatcher.parseStartIntent(packageManager, intent) if (BuildConfig.BUILD_TYPE == "dev" && WAIT_FOR_DEBUGGER) { @@ -219,20 +212,16 @@ abstract class BaseGodotEditor : GodotActivity() { } @CallSuper - protected open fun updateCommandLineParams(args: List) { - // Update the list of command line params with the new args - commandLineParams.clear() - if (args.isNotEmpty()) { - commandLineParams.addAll(args) - } - if (BuildConfig.BUILD_TYPE == "dev") { - commandLineParams.add("--benchmark") + protected override fun updateCommandLineParams(args: Array) { + val args = if (BuildConfig.BUILD_TYPE == "dev") { + args + "--benchmark" + } else { + args } + super.updateCommandLineParams(args); } - final override fun getCommandLine() = commandLineParams - - protected fun retrieveEditorWindowInfo(args: Array): EditorWindowInfo { + protected open fun retrieveEditorWindowInfo(args: Array): EditorWindowInfo { var hasEditor = false var xrMode = XR_MODE_DEFAULT @@ -335,14 +324,7 @@ abstract class BaseGodotEditor : GodotActivity() { val newInstance = getNewGodotInstanceIntent(editorWindowInfo, args) if (editorWindowInfo.windowClassName == javaClass.name) { Log.d(TAG, "Restarting ${editorWindowInfo.windowClassName} with parameters ${args.contentToString()}") - val godot = godot - if (godot != null) { - godot.destroyAndKillProcess { - ProcessPhoenix.triggerRebirth(this, activityOptions?.toBundle(), newInstance) - } - } else { - ProcessPhoenix.triggerRebirth(this, activityOptions?.toBundle(), newInstance) - } + triggerRebirth(activityOptions?.toBundle(), newInstance) } else { Log.d(TAG, "Starting ${editorWindowInfo.windowClassName} with parameters ${args.contentToString()}") newInstance.putExtra(EXTRA_NEW_LAUNCH, true) diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotXRGame.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotXRGame.kt index bfaef3abbd13..1b3018460765 100644 --- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotXRGame.kt +++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotXRGame.kt @@ -40,7 +40,7 @@ open class GodotXRGame: GodotGame() { override fun overrideOrientationRequest() = true - override fun updateCommandLineParams(args: List) { + override fun updateCommandLineParams(args: Array) { val updatedArgs = ArrayList() if (!args.contains(XRMode.OPENXR.cmdLineArg)) { updatedArgs.add(XRMode.OPENXR.cmdLineArg) @@ -51,7 +51,7 @@ open class GodotXRGame: GodotGame() { } updatedArgs.addAll(args) - super.updateCommandLineParams(updatedArgs) + super.updateCommandLineParams(updatedArgs.toTypedArray()) } override fun getEditorWindowInfo() = XR_RUN_GAME_INFO diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt index 3fc3caed9114..4c0192253dd5 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt @@ -823,9 +823,26 @@ class Godot(private val context: Context) { * Returns true if `Vulkan` is used for rendering. */ private fun usesVulkan(): Boolean { - val renderer = GodotLib.getGlobal("rendering/renderer/rendering_method") - val renderingDevice = GodotLib.getGlobal("rendering/rendering_device/driver") - return ("forward_plus" == renderer || "mobile" == renderer) && "vulkan" == renderingDevice + var rendererSource = "ProjectSettings" + var renderer = GodotLib.getGlobal("rendering/renderer/rendering_method") + var renderingDeviceSource = "ProjectSettings" + var renderingDevice = GodotLib.getGlobal("rendering/rendering_device/driver") + val cmdline = getCommandLine() + var index = cmdline.indexOf("--rendering-method") + if (index > -1 && cmdline.size > index + 1) { + rendererSource = "CommandLine" + renderer = cmdline.get(index + 1) + } + index = cmdline.indexOf("--rendering-driver") + if (index > -1 && cmdline.size > index + 1) { + renderingDeviceSource = "CommandLine" + renderingDevice = cmdline.get(index + 1) + } + val result = ("forward_plus" == renderer || "mobile" == renderer) && "vulkan" == renderingDevice + Log.d(TAG, """usesVulkan(): ${result} + renderingDevice: ${renderingDevice} (${renderingDeviceSource}) + renderer: ${renderer} (${rendererSource})""") + return result } /** diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt b/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt index 474c6e9b2fb2..72e63346fa0f 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt @@ -31,6 +31,7 @@ package org.godotengine.godot import android.app.Activity +import android.content.ComponentName import android.content.Intent import android.content.pm.PackageManager import android.os.Bundle @@ -52,18 +53,32 @@ abstract class GodotActivity : FragmentActivity(), GodotHost { companion object { private val TAG = GodotActivity::class.java.simpleName + @JvmStatic + protected val EXTRA_COMMAND_LINE_PARAMS = "command_line_params" + @JvmStatic protected val EXTRA_NEW_LAUNCH = "new_launch_requested" + + // This window must not match those in BaseGodotEditor.RUN_GAME_INFO etc + @JvmStatic + private final val DEFAULT_WINDOW_ID = 664; } + private val commandLineParams = ArrayList() /** * Interaction with the [Godot] object is delegated to the [GodotFragment] class. */ protected var godotFragment: GodotFragment? = null private set + @CallSuper override fun onCreate(savedInstanceState: Bundle?) { + val params = intent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS) + Log.d(TAG, "Starting intent $intent with parameters ${params.contentToString()}") + updateCommandLineParams(params ?: emptyArray()) + super.onCreate(savedInstanceState) + setContentView(getGodotAppLayout()) handleStartIntent(intent, true) @@ -79,6 +94,29 @@ abstract class GodotActivity : FragmentActivity(), GodotHost { } } + override fun onNewGodotInstanceRequested(args: Array): Int { + Log.d(TAG, "Restarting with parameters ${args.contentToString()}") + val intent = Intent() + .setComponent(ComponentName(this, javaClass.name)) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .putExtra(EXTRA_COMMAND_LINE_PARAMS, args) + triggerRebirth(null, intent) + // fake 'process' id returned by create_instance() etc + return DEFAULT_WINDOW_ID; + } + + protected fun triggerRebirth(bundle: Bundle?, intent: Intent) { + // Launch a new activity + val godot = godot + if (godot != null) { + godot.destroyAndKillProcess { + ProcessPhoenix.triggerRebirth(this, bundle, intent) + } + } else { + ProcessPhoenix.triggerRebirth(this, bundle, intent) + } + } + @LayoutRes protected open fun getGodotAppLayout() = R.layout.godot_app_layout @@ -176,4 +214,15 @@ abstract class GodotActivity : FragmentActivity(), GodotHost { protected open fun initGodotInstance(): GodotFragment { return GodotFragment() } + + @CallSuper + protected open fun updateCommandLineParams(args: Array) { + // Update the list of command line params with the new args + commandLineParams.clear() + if (args.isNotEmpty()) { + commandLineParams.addAll(args) + } + } + + final override fun getCommandLine() = commandLineParams }