-
-
Notifications
You must be signed in to change notification settings - Fork 21.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix create_instance in android GodotApp so non-editor apps can restart #101050
Fix create_instance in android GodotApp so non-editor apps can restart #101050
Conversation
751b5cc
to
826fa32
Compare
Tested on Pixel 8 and Meta Quest 3 allows switching rendering methods by calling
|
abcdad7
to
9dc9609
Compare
platform/android/java/editor/src/main/java/org/godotengine/editor/BaseGodotEditor.kt
Outdated
Show resolved
Hide resolved
66e2376
to
b182320
Compare
} | ||
if (BuildConfig.BUILD_TYPE == "dev") { | ||
commandLineParams.add("--benchmark") | ||
val args = if (BuildConfig.BUILD_TYPE == "dev") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new variable should have a different name otherwise it shadows the function parameter, and may lead to subtle bugs / mistakes when this method is updated in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO that's a feature, not a bug.. if you have multiple variables around that's when you might choose the wrong variable
https://discuss.kotlinlang.org/t/rust-style-variable-shadowing/16338
if there's only one 'args' then you can't use the 'wrong' one. I want to 'destroy' the old 'args' value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a fair argument.. I don't have a preference one way or another but since it seems to match the use-case here, it can remain as is. Note though that this would not work in the GodotXRGame
use-case since we're updating the arguments several times based on separate constraints.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes sense to me to add a bunch of stuff to a list, then call toTypedArray()
to pass it on in that case (which is how GodotXRGame.updateCommandLineParams()
works in this change)
- Really this method should be named
setCommandLineParams()
since it's only ever called once and always sets the entire array/list at once and each level only really calls it once to set it's arguments and then passes them to super(). - IMO The whole dance here is a bit much. To simplify I would eliminate this method and just make it a protected
List<String>
and let each level add it's own args. The consumer could callpublic getCommandLine(): Array<String>
to get the result after the end.- Paranoia: this may be too simple in some case that doesn't exist yet if arguments needed to be strictly ordered .. but it's a protected member so you'd just have to refactor it then, and currently it doesn't look like they do need to be strictly ordered.
- If
setCommandLineParams()
threw when it's too late then that would make sense though. - Right now I don't want to do any more refactoring in this change though, already have too much whiplash :D
@CallSuper | ||
protected open fun getNewGodotInstanceIntent(args: Array<String>): Intent { | ||
return Intent().setComponent(ComponentName(this, javaClass.name)) | ||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) | ||
.putExtra(EXTRA_COMMAND_LINE_PARAMS, args) | ||
} | ||
|
||
override fun onNewGodotInstanceRequested(args: Array<String>): Int { | ||
Log.d(TAG, "Restarting with parameters ${args.contentToString()}") | ||
triggerRebirth(null, getNewGodotInstanceIntent(args)) | ||
// fake 'process' id returned by create_instance() etc | ||
return DEFAULT_WINDOW_ID; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the triggerRebirth
function is a good idea! However, I don't see similar benefits with getNewGodotInstanceIntent
and onNewGodotInstanceRequested
. The latter especially is different enough between the two classes that there's not much benefit in trying to extract common functionality, so I'd just leave it as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This functionality is needed here since I removed it from GodotApp to avoid kotlin/java interop..
The default behavior (here) is used by GodotApp, BaseGodotEditor doesn't call super.onNewGodotInstanceRequested(...)
since the only common functionality is triggerRebirth()
For getNewGodotInstanceIntent()
:
I feel that addFlags() and putExtra() are enough common functionality between GodotActivity and BaseGodotEditor, since they both need those basic intent options configured to function. (BaseGodotEditor just calls intent.setComponent()
again to override the classname.
I thought about renaming it to getNewGodotEditorInstanceIntent(...)
just to avoid calling retrieveEditorWindowInfo()
twice...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This functionality is needed here since I removed it from GodotApp to avoid kotlin/java interop..
What's the interop issue you're referring to?
For getNewGodotInstanceIntent():
I feel that addFlags() and putExtra() are enough common functionality between GodotActivity and BaseGodotEditor, since they both need those basic intent options configured to function. (BaseGodotEditor just calls intent.setComponent() again to override the classname.
Let's remove this one.. creating an intent is simple enough that we don't really need an helper method for it. In addition, each subclass has different requirements on how they need to configure their intent and the arguments they're passing to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This functionality is needed here since I removed it from GodotApp to avoid kotlin/java interop..
What's the interop issue you're referring to?
I interop works fine but the impedance mismatch is higher than expected to call across the two. Specifically this
getEXTRA_COMMAND_LINE_PARAMS()
quirk caused me to decide that It's better to just write as much of this change in GodotActivity.kt
to avoid crossing between java and kotlin.
Let's remove this one..
Done.
platform/android/java/editor/src/horizonos/java/org/godotengine/editor/GodotXRGame.kt
Outdated
Show resolved
Hide resolved
b182320
to
298bfe3
Compare
I tested the Android Editor with this project: It restart the Editor when tried to change the renderer. And the PIP button also apear in editor. az_recorder_20250109_094022_edited.mp4 |
This would be a separate issue.
|
I know that. But I was expecting a warning. No behavior like this. when calling those function you could just show a wearing and do noting. For better debuning. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost ready for approval!
} | ||
if (BuildConfig.BUILD_TYPE == "dev") { | ||
commandLineParams.add("--benchmark") | ||
val args = if (BuildConfig.BUILD_TYPE == "dev") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a fair argument.. I don't have a preference one way or another but since it seems to match the use-case here, it can remain as is. Note though that this would not work in the GodotXRGame
use-case since we're updating the arguments several times based on separate constraints.
if (BuildConfig.BUILD_TYPE == "dev") { | ||
commandLineParams.add("--benchmark") | ||
val args = if (BuildConfig.BUILD_TYPE == "dev") { | ||
arrayOf(*args, "--benchmark") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: here you can just return args + "--benchmark"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect, loving kotlin more the more I learn of the syntax!
@CallSuper | ||
protected open fun getNewGodotInstanceIntent(args: Array<String>): Intent { | ||
return Intent().setComponent(ComponentName(this, javaClass.name)) | ||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) | ||
.putExtra(EXTRA_COMMAND_LINE_PARAMS, args) | ||
} | ||
|
||
override fun onNewGodotInstanceRequested(args: Array<String>): Int { | ||
Log.d(TAG, "Restarting with parameters ${args.contentToString()}") | ||
triggerRebirth(null, getNewGodotInstanceIntent(args)) | ||
// fake 'process' id returned by create_instance() etc | ||
return DEFAULT_WINDOW_ID; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This functionality is needed here since I removed it from GodotApp to avoid kotlin/java interop..
What's the interop issue you're referring to?
For getNewGodotInstanceIntent():
I feel that addFlags() and putExtra() are enough common functionality between GodotActivity and BaseGodotEditor, since they both need those basic intent options configured to function. (BaseGodotEditor just calls intent.setComponent() again to override the classname.
Let's remove this one.. creating an intent is simple enough that we don't really need an helper method for it. In addition, each subclass has different requirements on how they need to configure their intent and the arguments they're passing to it.
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: godotengine/godot-proposals#6423
298bfe3
to
605b970
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙏
} | ||
if (BuildConfig.BUILD_TYPE == "dev") { | ||
commandLineParams.add("--benchmark") | ||
val args = if (BuildConfig.BUILD_TYPE == "dev") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes sense to me to add a bunch of stuff to a list, then call toTypedArray()
to pass it on in that case (which is how GodotXRGame.updateCommandLineParams()
works in this change)
- Really this method should be named
setCommandLineParams()
since it's only ever called once and always sets the entire array/list at once and each level only really calls it once to set it's arguments and then passes them to super(). - IMO The whole dance here is a bit much. To simplify I would eliminate this method and just make it a protected
List<String>
and let each level add it's own args. The consumer could callpublic getCommandLine(): Array<String>
to get the result after the end.- Paranoia: this may be too simple in some case that doesn't exist yet if arguments needed to be strictly ordered .. but it's a protected member so you'd just have to refactor it then, and currently it doesn't look like they do need to be strictly ordered.
- If
setCommandLineParams()
threw when it's too late then that would make sense though. - Right now I don't want to do any more refactoring in this change though, already have too much whiplash :D
if (BuildConfig.BUILD_TYPE == "dev") { | ||
commandLineParams.add("--benchmark") | ||
val args = if (BuildConfig.BUILD_TYPE == "dev") { | ||
arrayOf(*args, "--benchmark") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect, loving kotlin more the more I learn of the syntax!
@CallSuper | ||
protected open fun getNewGodotInstanceIntent(args: Array<String>): Intent { | ||
return Intent().setComponent(ComponentName(this, javaClass.name)) | ||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) | ||
.putExtra(EXTRA_COMMAND_LINE_PARAMS, args) | ||
} | ||
|
||
override fun onNewGodotInstanceRequested(args: Array<String>): Int { | ||
Log.d(TAG, "Restarting with parameters ${args.contentToString()}") | ||
triggerRebirth(null, getNewGodotInstanceIntent(args)) | ||
// fake 'process' id returned by create_instance() etc | ||
return DEFAULT_WINDOW_ID; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This functionality is needed here since I removed it from GodotApp to avoid kotlin/java interop..
What's the interop issue you're referring to?
I interop works fine but the impedance mismatch is higher than expected to call across the two. Specifically this
getEXTRA_COMMAND_LINE_PARAMS()
quirk caused me to decide that It's better to just write as much of this change in GodotActivity.kt
to avoid crossing between java and kotlin.
Let's remove this one..
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Thanks for the fix!
final override fun getCommandLine() = commandLineParams | ||
|
||
protected fun retrieveEditorWindowInfo(args: Array<String>): EditorWindowInfo { | ||
protected open fun retrieveEditorWindowInfo(args: Array<String>): EditorWindowInfo { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this change can be reverted
@syntaxerror247 i think this is ready :D |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Thanks!
Thanks! |
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:
#31541
godotengine/godot-proposals#6423