@@ -62,6 +62,10 @@ import org.godotengine.godot.io.file.FileAccessHandler
6262import org.godotengine.godot.plugin.AndroidRuntimePlugin
6363import org.godotengine.godot.plugin.GodotPlugin
6464import org.godotengine.godot.plugin.GodotPluginRegistry
65+ import org.godotengine.godot.render.GodotGLRenderView
66+ import org.godotengine.godot.render.GodotRenderer
67+ import org.godotengine.godot.render.GodotVulkanRenderView
68+ import org.godotengine.godot.render.Renderer
6569import org.godotengine.godot.tts.GodotTTS
6670import org.godotengine.godot.utils.DialogUtils
6771import org.godotengine.godot.utils.GodotNetUtils
@@ -112,6 +116,8 @@ class Godot private constructor(val context: Context) {
112116 internal fun isEditorBuild () = BuildConfig .FLAVOR == EDITOR_FLAVOR
113117 }
114118
119+ private lateinit var renderer: GodotRenderer
120+
115121 private val mSensorManager: SensorManager ? by lazy { context.getSystemService(Context .SENSOR_SERVICE ) as ? SensorManager }
116122 private val mClipboard: ClipboardManager ? by lazy { context.getSystemService(Context .CLIPBOARD_SERVICE ) as ? ClipboardManager }
117123 private val vibratorService: Vibrator ? by lazy { context.getSystemService(Context .VIBRATOR_SERVICE ) as ? Vibrator }
@@ -133,7 +139,7 @@ class Godot private constructor(val context: Context) {
133139 val directoryAccessHandler = DirectoryAccessHandler (context)
134140 val fileAccessHandler = FileAccessHandler (context)
135141 val netUtils = GodotNetUtils (context)
136- private val godotInputHandler = GodotInputHandler (context, this )
142+ val godotInputHandler = GodotInputHandler (context, this )
137143
138144 /* *
139145 * Task to run when the engine terminates.
@@ -182,18 +188,23 @@ class Godot private constructor(val context: Context) {
182188 /* *
183189 * Returns true if the native engine has been initialized through [onInitNativeLayer], false otherwise.
184190 */
185- private fun isNativeInitialized () = nativeLayerInitializeCompleted && nativeLayerSetupCompleted
191+ private fun isNativeInitialized () = nativeLayerInitializeCompleted && nativeLayerSetupCompleted && ::renderer.isInitialized
186192
187193 /* *
188194 * Returns true if the engine has been initialized, false otherwise.
189195 */
190196 fun isInitialized () = primaryHost != null && isNativeInitialized() && renderViewInitialized
191197
192198 /* *
193- * Provides access to the primary host [Activity]
199+ * Provides access to the primary host [Activity].
194200 */
195201 fun getActivity () = primaryHost?.activity
196202
203+ /* *
204+ * Provides access to the Godot [Renderer].
205+ */
206+ fun getRenderer (): Renderer = renderer
207+
197208 /* *
198209 * Start initialization of the Godot engine.
199210 *
@@ -331,6 +342,21 @@ class Godot private constructor(val context: Context) {
331342 Log .v(TAG , " Godot native layer setup completed" )
332343 }
333344 }
345+
346+ val useVulkan = if (usesVulkan()) {
347+ if (meetsVulkanRequirements(context.packageManager)) {
348+ true
349+ } else if (canFallbackToOpenGL()) {
350+ // Fallback to OpenGl.
351+ false
352+ } else {
353+ throw IllegalStateException (context.getString(R .string.error_missing_vulkan_requirements_message))
354+ }
355+ } else {
356+ false
357+ }
358+ renderer = GodotRenderer (useVulkan)
359+ renderer.startRenderer()
334360 } finally {
335361 endBenchmarkMeasure(" Startup" , " Godot::initEngine" )
336362 }
@@ -489,23 +515,13 @@ class Godot private constructor(val context: Context) {
489515 val shouldBeTransparent =
490516 ! isProjectManagerHint() && ! isEditorHint() && java.lang.Boolean .parseBoolean(GodotLib .getGlobal(" display/window/per_pixel_transparency/allowed" ))
491517 Log .d(TAG , " Render view should be transparent: $shouldBeTransparent " )
492- renderView = if (usesVulkan()) {
493- if (meetsVulkanRequirements(context.packageManager)) {
494- GodotVulkanRenderView (this , godotInputHandler, shouldBeTransparent)
495- } else if (canFallbackToOpenGL()) {
496- // Fallback to OpenGl.
497- GodotGLRenderView (this , godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent)
498- } else {
499- throw IllegalStateException (context.getString(R .string.error_missing_vulkan_requirements_message))
500- }
501-
518+ renderView = if (renderer.useVulkan) {
519+ GodotVulkanRenderView (this , renderer, godotInputHandler, shouldBeTransparent)
502520 } else {
503- // Fallback to OpenGl.
504- GodotGLRenderView (this , godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent)
521+ GodotGLRenderView (this , renderer, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent)
505522 }
506523
507524 renderView?.let {
508- it.startRenderer()
509525 containerLayout?.addView(
510526 it.view,
511527 ViewGroup .LayoutParams (
@@ -557,7 +573,7 @@ class Godot private constructor(val context: Context) {
557573 override fun onEnd (animation : WindowInsetsAnimationCompat ) {}
558574 })
559575
560- renderView?.queueOnRenderThread {
576+ runOnRenderThread {
561577 for (plugin in pluginRegistry.allPlugins) {
562578 plugin.onRegisterPluginWithGodotNative()
563579 }
@@ -593,7 +609,10 @@ class Godot private constructor(val context: Context) {
593609 return
594610 }
595611
596- renderView?.onActivityStarted()
612+ renderer.onActivityStarted()
613+ for (plugin in pluginRegistry.allPlugins) {
614+ plugin.onMainStart()
615+ }
597616 }
598617
599618 fun onResume (host : GodotHost ) {
@@ -603,7 +622,7 @@ class Godot private constructor(val context: Context) {
603622 return
604623 }
605624
606- renderView? .onActivityResumed()
625+ renderer .onActivityResumed()
607626 registerSensorsIfNeeded()
608627 for (plugin in pluginRegistry.allPlugins) {
609628 plugin.onMainResume()
@@ -636,11 +655,11 @@ class Godot private constructor(val context: Context) {
636655 return
637656 }
638657
639- renderView?.onActivityPaused()
640- mSensorManager?.unregisterListener(godotInputHandler)
641658 for (plugin in pluginRegistry.allPlugins) {
642659 plugin.onMainPause()
643660 }
661+ renderer.onActivityPaused()
662+ mSensorManager?.unregisterListener(godotInputHandler)
644663 }
645664
646665 fun onStop (host : GodotHost ) {
@@ -649,7 +668,10 @@ class Godot private constructor(val context: Context) {
649668 return
650669 }
651670
652- renderView?.onActivityStopped()
671+ for (plugin in pluginRegistry.allPlugins) {
672+ plugin.onMainStop()
673+ }
674+ renderer.onActivityStopped()
653675 }
654676
655677 fun onDestroy (primaryHost : GodotHost ) {
@@ -658,12 +680,22 @@ class Godot private constructor(val context: Context) {
658680 }
659681 Log .v(TAG , " OnDestroy: $primaryHost " )
660682
683+ // If the host activity is being destroyed because it's changing configurations, it'll be recreated, so we keep
684+ // the engine around to continue where we left off.
685+ val isHostChangingConfigurations = primaryHost.activity?.isChangingConfigurations == true
686+ if (! isHostChangingConfigurations) {
687+ destroyEngine()
688+ }
689+ this .primaryHost = null
690+ }
691+
692+ private fun destroyEngine () {
693+ Log .d(TAG , " Destroying Godot Engine" )
661694 for (plugin in pluginRegistry.allPlugins) {
662695 plugin.onMainDestroy()
663696 }
664697
665- renderView?.onActivityDestroyed()
666- this .primaryHost = null
698+ renderer.onActivityDestroyed()
667699 }
668700
669701 /* *
@@ -724,7 +756,7 @@ class Godot private constructor(val context: Context) {
724756 val scrollDeadzoneDisabled = java.lang.Boolean .parseBoolean(GodotLib .getGlobal(" input_devices/pointing/android/disable_scroll_deadzone" ))
725757
726758 runOnHostThread {
727- renderView?.inputHandler? .apply {
759+ godotInputHandler .apply {
728760 enableLongPress(longPressEnabled)
729761 enablePanningAndScalingGestures(panScaleEnabled)
730762 setOverrideVolumeButtons(overrideVolumeButtons)
@@ -811,7 +843,7 @@ class Godot private constructor(val context: Context) {
811843 * This must be called after the render thread has started.
812844 */
813845 fun runOnRenderThread (action : Runnable ) {
814- renderView? .queueOnRenderThread(action)
846+ renderer .queueOnRenderThread(action)
815847 }
816848
817849 /* *
@@ -983,7 +1015,7 @@ class Godot private constructor(val context: Context) {
9831015 runOnTerminate.set(destroyRunnable)
9841016
9851017 runOnHostThread {
986- onDestroy(host )
1018+ destroyEngine( )
9871019 }
9881020 }
9891021
@@ -1003,7 +1035,7 @@ class Godot private constructor(val context: Context) {
10031035 for (plugin in pluginRegistry.allPlugins) {
10041036 plugin.onMainBackPressed()
10051037 }
1006- renderView?.queueOnRenderThread { GodotLib .back() }
1038+ runOnRenderThread { GodotLib .back() }
10071039 }
10081040
10091041 /* *
0 commit comments