Merge pull request #92704 from m4gr3d/update_android_editor_activity_layout
Consolidate the ProjectManager and Editor windows into a single Android Activity class
This commit is contained in:
commit
62b15238e5
|
@ -32,13 +32,11 @@
|
||||||
android:requestLegacyExternalStorage="true">
|
android:requestLegacyExternalStorage="true">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".GodotProjectManager"
|
android:name=".GodotEditor"
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:screenOrientation="userLandscape"
|
android:screenOrientation="userLandscape"
|
||||||
android:exported="true"
|
android:exported="true">
|
||||||
android:process=":GodotProjectManager">
|
|
||||||
|
|
||||||
<layout android:defaultHeight="@dimen/editor_default_window_height"
|
<layout android:defaultHeight="@dimen/editor_default_window_height"
|
||||||
android:defaultWidth="@dimen/editor_default_window_width" />
|
android:defaultWidth="@dimen/editor_default_window_width" />
|
||||||
|
|
||||||
|
@ -49,17 +47,6 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".GodotEditor"
|
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
|
||||||
android:process=":GodotEditor"
|
|
||||||
android:launchMode="singleTask"
|
|
||||||
android:screenOrientation="userLandscape"
|
|
||||||
android:exported="false">
|
|
||||||
<layout android:defaultHeight="@dimen/editor_default_window_height"
|
|
||||||
android:defaultWidth="@dimen/editor_default_window_width" />
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".GodotGame"
|
android:name=".GodotGame"
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/* GodotProjectManager.kt */
|
/* EditorWindowInfo.kt */
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/* This file is part of: */
|
/* This file is part of: */
|
||||||
/* GODOT ENGINE */
|
/* GODOT ENGINE */
|
||||||
|
@ -31,14 +31,38 @@
|
||||||
package org.godotengine.editor
|
package org.godotengine.editor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launcher activity for the Godot Android Editor.
|
* Specifies the policy for adjacent launches.
|
||||||
*
|
|
||||||
* It presents the user with the project manager interface.
|
|
||||||
* Upon selection of a project, this activity (via its parent logic) starts the
|
|
||||||
* [GodotEditor] activity.
|
|
||||||
*/
|
*/
|
||||||
class GodotProjectManager : GodotEditor() {
|
enum class LaunchAdjacentPolicy {
|
||||||
override fun checkForProjectPermissionsToEnable() {
|
/**
|
||||||
// Nothing to do here.. we have yet to select a project to load.
|
* Adjacent launches are disabled.
|
||||||
}
|
*/
|
||||||
|
DISABLED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjacent launches are enabled / disabled based on the device and screen metrics.
|
||||||
|
*/
|
||||||
|
AUTO,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjacent launches are enabled.
|
||||||
|
*/
|
||||||
|
ENABLED
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describe the editor window to launch
|
||||||
|
*/
|
||||||
|
data class EditorWindowInfo(
|
||||||
|
val windowClassName: String,
|
||||||
|
val windowId: Int,
|
||||||
|
val processNameSuffix: String,
|
||||||
|
val launchAdjacentPolicy: LaunchAdjacentPolicy = LaunchAdjacentPolicy.DISABLED
|
||||||
|
) {
|
||||||
|
constructor(
|
||||||
|
windowClass: Class<*>,
|
||||||
|
windowId: Int,
|
||||||
|
processNameSuffix: String,
|
||||||
|
launchAdjacentPolicy: LaunchAdjacentPolicy = LaunchAdjacentPolicy.DISABLED
|
||||||
|
) : this(windowClass.name, windowId, processNameSuffix, launchAdjacentPolicy)
|
||||||
}
|
}
|
|
@ -32,12 +32,14 @@ package org.godotengine.editor
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.*
|
import android.os.*
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.CallSuper
|
||||||
import androidx.window.layout.WindowMetricsCalculator
|
import androidx.window.layout.WindowMetricsCalculator
|
||||||
import org.godotengine.godot.GodotActivity
|
import org.godotengine.godot.GodotActivity
|
||||||
import org.godotengine.godot.GodotLib
|
import org.godotengine.godot.GodotLib
|
||||||
|
@ -64,18 +66,15 @@ open class GodotEditor : GodotActivity() {
|
||||||
|
|
||||||
private const val EXTRA_COMMAND_LINE_PARAMS = "command_line_params"
|
private const val EXTRA_COMMAND_LINE_PARAMS = "command_line_params"
|
||||||
|
|
||||||
private const val EDITOR_ID = 777
|
// Command line arguments
|
||||||
private const val EDITOR_ARG = "--editor"
|
private const val EDITOR_ARG = "--editor"
|
||||||
private const val EDITOR_ARG_SHORT = "-e"
|
private const val EDITOR_ARG_SHORT = "-e"
|
||||||
private const val EDITOR_PROCESS_NAME_SUFFIX = ":GodotEditor"
|
private const val EDITOR_PROJECT_MANAGER_ARG = "--project-manager"
|
||||||
|
private const val EDITOR_PROJECT_MANAGER_ARG_SHORT = "-p"
|
||||||
|
|
||||||
private const val GAME_ID = 667
|
// Info for the various classes used by the editor
|
||||||
private const val GAME_PROCESS_NAME_SUFFIX = ":GodotGame"
|
internal val EDITOR_MAIN_INFO = EditorWindowInfo(GodotEditor::class.java, 777, "")
|
||||||
|
internal val RUN_GAME_INFO = EditorWindowInfo(GodotGame::class.java, 667, ":GodotGame", LaunchAdjacentPolicy.AUTO)
|
||||||
private const val PROJECT_MANAGER_ID = 555
|
|
||||||
private const val PROJECT_MANAGER_ARG = "--project-manager"
|
|
||||||
private const val PROJECT_MANAGER_ARG_SHORT = "-p"
|
|
||||||
private const val PROJECT_MANAGER_PROCESS_NAME_SUFFIX = ":GodotProjectManager"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets of constants to specify the window to use to run the project.
|
* Sets of constants to specify the window to use to run the project.
|
||||||
|
@ -96,8 +95,8 @@ open class GodotEditor : GodotActivity() {
|
||||||
PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO))
|
PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO))
|
||||||
|
|
||||||
val params = intent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS)
|
val params = intent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS)
|
||||||
Log.d(TAG, "Received parameters ${params.contentToString()}")
|
Log.d(TAG, "Starting intent $intent with parameters ${params.contentToString()}")
|
||||||
updateCommandLineParams(params)
|
updateCommandLineParams(params?.asList() ?: emptyList())
|
||||||
|
|
||||||
if (BuildConfig.BUILD_TYPE == "dev" && WAIT_FOR_DEBUGGER) {
|
if (BuildConfig.BUILD_TYPE == "dev" && WAIT_FOR_DEBUGGER) {
|
||||||
Debug.waitForDebugger()
|
Debug.waitForDebugger()
|
||||||
|
@ -133,98 +132,85 @@ open class GodotEditor : GodotActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateCommandLineParams(args: Array<String>?) {
|
@CallSuper
|
||||||
|
protected open fun updateCommandLineParams(args: List<String>) {
|
||||||
// Update the list of command line params with the new args
|
// Update the list of command line params with the new args
|
||||||
commandLineParams.clear()
|
commandLineParams.clear()
|
||||||
if (!args.isNullOrEmpty()) {
|
if (args.isNotEmpty()) {
|
||||||
commandLineParams.addAll(listOf(*args))
|
commandLineParams.addAll(args)
|
||||||
}
|
}
|
||||||
if (BuildConfig.BUILD_TYPE == "dev") {
|
if (BuildConfig.BUILD_TYPE == "dev") {
|
||||||
commandLineParams.add("--benchmark")
|
commandLineParams.add("--benchmark")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getCommandLine() = commandLineParams
|
final override fun getCommandLine() = commandLineParams
|
||||||
|
|
||||||
|
protected open fun getEditorWindowInfo(args: Array<String>): EditorWindowInfo {
|
||||||
|
var hasEditor = 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (hasEditor) {
|
||||||
|
EDITOR_MAIN_INFO
|
||||||
|
} else {
|
||||||
|
RUN_GAME_INFO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun getEditorWindowInfoForInstanceId(instanceId: Int): EditorWindowInfo? {
|
||||||
|
return when (instanceId) {
|
||||||
|
RUN_GAME_INFO.windowId -> RUN_GAME_INFO
|
||||||
|
EDITOR_MAIN_INFO.windowId -> EDITOR_MAIN_INFO
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onNewGodotInstanceRequested(args: Array<String>): Int {
|
override fun onNewGodotInstanceRequested(args: Array<String>): Int {
|
||||||
// Parse the arguments to figure out which activity to start.
|
val editorWindowInfo = getEditorWindowInfo(args)
|
||||||
var targetClass: Class<*> = GodotGame::class.java
|
|
||||||
var instanceId = GAME_ID
|
|
||||||
|
|
||||||
// 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 = shouldGameLaunchAdjacent()
|
|
||||||
|
|
||||||
for (arg in args) {
|
|
||||||
if (EDITOR_ARG == arg || EDITOR_ARG_SHORT == arg) {
|
|
||||||
targetClass = GodotEditor::class.java
|
|
||||||
launchAdjacent = false
|
|
||||||
instanceId = EDITOR_ID
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PROJECT_MANAGER_ARG == arg || PROJECT_MANAGER_ARG_SHORT == arg) {
|
|
||||||
targetClass = GodotProjectManager::class.java
|
|
||||||
launchAdjacent = false
|
|
||||||
instanceId = PROJECT_MANAGER_ID
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Launch a new activity
|
// Launch a new activity
|
||||||
val newInstance = Intent(this, targetClass)
|
val newInstance = Intent()
|
||||||
|
.setComponent(ComponentName(this, editorWindowInfo.windowClassName))
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
.putExtra(EXTRA_COMMAND_LINE_PARAMS, args)
|
.putExtra(EXTRA_COMMAND_LINE_PARAMS, args)
|
||||||
if (launchAdjacent) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
newInstance.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT)
|
if (editorWindowInfo.launchAdjacentPolicy == LaunchAdjacentPolicy.ENABLED ||
|
||||||
|
(editorWindowInfo.launchAdjacentPolicy == LaunchAdjacentPolicy.AUTO && shouldGameLaunchAdjacent())) {
|
||||||
|
Log.v(TAG, "Adding flag for adjacent launch")
|
||||||
|
newInstance.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (targetClass == javaClass) {
|
if (editorWindowInfo.windowClassName == javaClass.name) {
|
||||||
Log.d(TAG, "Restarting $targetClass with parameters ${args.contentToString()}")
|
Log.d(TAG, "Restarting ${editorWindowInfo.windowClassName} with parameters ${args.contentToString()}")
|
||||||
ProcessPhoenix.triggerRebirth(this, newInstance)
|
ProcessPhoenix.triggerRebirth(this, newInstance)
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "Starting $targetClass with parameters ${args.contentToString()}")
|
Log.d(TAG, "Starting ${editorWindowInfo.windowClassName} with parameters ${args.contentToString()}")
|
||||||
newInstance.putExtra(EXTRA_NEW_LAUNCH, true)
|
newInstance.putExtra(EXTRA_NEW_LAUNCH, true)
|
||||||
startActivity(newInstance)
|
startActivity(newInstance)
|
||||||
}
|
}
|
||||||
return instanceId
|
return editorWindowInfo.windowId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onGodotForceQuit(godotInstanceId: Int): Boolean {
|
final override fun onGodotForceQuit(godotInstanceId: Int): Boolean {
|
||||||
val targetClass: Class<*>?
|
val editorWindowInfo = getEditorWindowInfoForInstanceId(godotInstanceId) ?: return super.onGodotForceQuit(godotInstanceId)
|
||||||
val processNameSuffix: String
|
|
||||||
when (godotInstanceId) {
|
|
||||||
GAME_ID -> {
|
|
||||||
processNameSuffix = GAME_PROCESS_NAME_SUFFIX
|
|
||||||
targetClass = GodotGame::class.java
|
|
||||||
}
|
|
||||||
EDITOR_ID -> {
|
|
||||||
processNameSuffix = EDITOR_PROCESS_NAME_SUFFIX
|
|
||||||
targetClass = GodotEditor::class.java
|
|
||||||
}
|
|
||||||
PROJECT_MANAGER_ID -> {
|
|
||||||
processNameSuffix = PROJECT_MANAGER_PROCESS_NAME_SUFFIX
|
|
||||||
targetClass = GodotProjectManager::class.java
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
processNameSuffix = ""
|
|
||||||
targetClass = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetClass == javaClass) {
|
if (editorWindowInfo.windowClassName == javaClass.name) {
|
||||||
Log.d(TAG, "Force quitting $targetClass")
|
Log.d(TAG, "Force quitting ${editorWindowInfo.windowClassName}")
|
||||||
ProcessPhoenix.forceQuit(this)
|
ProcessPhoenix.forceQuit(this)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (processNameSuffix.isBlank()) {
|
val processName = packageName + editorWindowInfo.processNameSuffix
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
||||||
val runningProcesses = activityManager.runningAppProcesses
|
val runningProcesses = activityManager.runningAppProcesses
|
||||||
for (runningProcess in runningProcesses) {
|
for (runningProcess in runningProcesses) {
|
||||||
if (runningProcess.processName.endsWith(processNameSuffix)) {
|
if (runningProcess.processName == processName) {
|
||||||
// Killing process directly
|
// Killing process directly
|
||||||
Log.v(TAG, "Killing Godot process ${runningProcess.processName}")
|
Log.v(TAG, "Killing Godot process ${runningProcess.processName}")
|
||||||
Process.killProcess(runningProcess.pid)
|
Process.killProcess(runningProcess.pid)
|
||||||
|
@ -232,11 +218,11 @@ open class GodotEditor : GodotActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return super.onGodotForceQuit(godotInstanceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the screen's density scale
|
// Get the screen's density scale
|
||||||
protected val isLargeScreen: Boolean
|
private val isLargeScreen: Boolean
|
||||||
// Get the minimum window size // Correspond to the EXPANDED window size class.
|
// Get the minimum window size // Correspond to the EXPANDED window size class.
|
||||||
get() {
|
get() {
|
||||||
val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this)
|
val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this)
|
||||||
|
@ -273,6 +259,10 @@ open class GodotEditor : GodotActivity() {
|
||||||
protected open fun enablePanAndScaleGestures() =
|
protected open fun enablePanAndScaleGestures() =
|
||||||
java.lang.Boolean.parseBoolean(GodotLib.getEditorSetting("interface/touchscreen/enable_pan_and_scale_gestures"))
|
java.lang.Boolean.parseBoolean(GodotLib.getEditorSetting("interface/touchscreen/enable_pan_and_scale_gestures"))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether we should launch the new godot instance in an adjacent window
|
||||||
|
* @see https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_LAUNCH_ADJACENT
|
||||||
|
*/
|
||||||
private fun shouldGameLaunchAdjacent(): Boolean {
|
private fun shouldGameLaunchAdjacent(): Boolean {
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in New Issue