From 259b388214d1886e52a47028b358488c79f63cb3 Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Sun, 28 Jan 2024 10:10:59 +0100 Subject: [PATCH] World screen resize delayed (#11015) * Coalesce repeated WorldScreen resize events to avoid multiple concurrent loadGame coroutines * Remove resize instrumentation --- .../ui/screens/worldscreen/WorldScreen.kt | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/core/src/com/unciv/ui/screens/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/screens/worldscreen/WorldScreen.kt index 8678135900..58248d9ea8 100644 --- a/core/src/com/unciv/ui/screens/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/screens/worldscreen/WorldScreen.kt @@ -69,6 +69,8 @@ import com.unciv.utils.launchOnThreadPool import com.unciv.utils.withGLContext import kotlinx.coroutines.Job import kotlinx.coroutines.coroutineScope +import java.util.Timer +import kotlin.concurrent.timer /** * Do not create this screen without seriously thinking about the implications: this is the single most memory-intensive class in the application. @@ -216,6 +218,7 @@ class WorldScreen( } override fun dispose() { + resizeDeferTimer?.cancel() events.stopReceiving() statusButtons.dispose() super.dispose() @@ -715,17 +718,23 @@ class WorldScreen( } } + + private var resizeDeferTimer: Timer? = null + override fun resize(width: Int, height: Int) { - if (stage.viewport.screenWidth != width || stage.viewport.screenHeight != height) { + resizeDeferTimer?.cancel() + if (resizeDeferTimer == null && stage.viewport.screenWidth == width && stage.viewport.screenHeight == height) return + resizeDeferTimer = timer("Resize", daemon = true, 500L, Long.MAX_VALUE) { + resizeDeferTimer?.cancel() + resizeDeferTimer = null startNewScreenJob(gameInfo, true) // start over } } - override fun render(delta: Float) { // This is so that updates happen in the MAIN THREAD, where there is a GL Context, // otherwise images will not load properly! - if (shouldUpdate) { + if (shouldUpdate && resizeDeferTimer == null) { shouldUpdate = false // Since updating the worldscreen can take a long time, *especially* the first time, we disable input processing to avoid ANRs @@ -735,12 +744,11 @@ class WorldScreen( if (Gdx.input.inputProcessor == null) // Update may have replaced the worldscreen with a GreatPersonPickerScreen etc, so the input would already be set Gdx.input.inputProcessor = stage } -// topBar.selectedCivLabel.setText(Gdx.graphics.framesPerSecond) // for framerate testing - super.render(delta) } + private fun showTutorialsOnNextTurn() { if (!game.settings.showTutorials) return displayTutorial(TutorialTrigger.SlowStart) @@ -799,7 +807,7 @@ class WorldScreen( } /** This exists so that no reference to the current world screen remains, so the old world screen can get garbage collected during [UncivGame.loadGame]. */ -private fun startNewScreenJob(gameInfo: GameInfo, autosaveDisabled:Boolean = false) { +private fun startNewScreenJob(gameInfo: GameInfo, autosaveDisabled: Boolean = false) { Concurrency.run { val newWorldScreen = try { UncivGame.Current.loadGame(gameInfo)