From f3fb8a96f0165b12d187299cb61bdb8b7de101d3 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Mon, 6 Apr 2026 02:05:05 +0900 Subject: [PATCH] more interesting splash screen wip --- src/net/torvald/terrarum/App.java | 3 + .../torvald/terrarum/CommonResourcePool.kt | 11 ++++ src/net/torvald/terrarum/SplashScreen.kt | 63 +++++++++++++++++++ .../torvald/terrarum/ui/UIItemHorzSlider.kt | 2 +- .../torvald/terrarum/ui/UIItemVertSlider.kt | 2 +- 5 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 src/net/torvald/terrarum/SplashScreen.kt diff --git a/src/net/torvald/terrarum/App.java b/src/net/torvald/terrarum/App.java index 57cfa4f1a..cb84ed3ef 100644 --- a/src/net/torvald/terrarum/App.java +++ b/src/net/torvald/terrarum/App.java @@ -946,6 +946,9 @@ public class App implements ApplicationListener { logoBatch.end(); + // draw loading bar and subtitle + SplashScreen.render(logoBatch, camera); + // draw health messages if (getConfigBoolean("showhealthmessageonstartup")) { logoBatch.setShader(null); diff --git a/src/net/torvald/terrarum/CommonResourcePool.kt b/src/net/torvald/terrarum/CommonResourcePool.kt index d35a0a497..3248ed7ee 100644 --- a/src/net/torvald/terrarum/CommonResourcePool.kt +++ b/src/net/torvald/terrarum/CommonResourcePool.kt @@ -31,6 +31,16 @@ object CommonResourcePool { private val slowLoadingQueue = ConcurrentLinkedQueue() private val slowLoadingRemaining = AtomicInteger(0) + private val slowLoadingTotal = AtomicInteger(0) + + /** 0.0 = not started yet, 1.0 = all done. Only meaningful during / after [loadAllSlowly]. */ + val loadingProgress: Float + get() { + val total = slowLoadingTotal.get() + if (total == 0) return 0f + val remaining = slowLoadingRemaining.get() + return (total - remaining).toFloat() / total.toFloat() + } fun setGLThread(thread: Thread) { glThread = thread @@ -152,6 +162,7 @@ object CommonResourcePool { val desc = loadingList.removeFirst() slowLoadingQueue.add(desc) slowLoadingRemaining.incrementAndGet() + slowLoadingTotal.incrementAndGet() } // Block until the GL thread has processed all slow items while (slowLoadingRemaining.get() > 0) { diff --git a/src/net/torvald/terrarum/SplashScreen.kt b/src/net/torvald/terrarum/SplashScreen.kt new file mode 100644 index 000000000..23e750d1f --- /dev/null +++ b/src/net/torvald/terrarum/SplashScreen.kt @@ -0,0 +1,63 @@ +package net.torvald.terrarum + +import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.graphics.OrthographicCamera +import com.badlogic.gdx.graphics.g2d.SpriteBatch +import net.torvald.terrarum.ui.Toolkit +import net.torvald.terrarum.ui.UICanvas +import net.torvald.terrarum.ui.UIItemHorzSlider + +/** + * Draws the loading bar and subtitle on the cold-boot splash screen. + * Called from App.drawSplash() (Java static context) on the GL thread. + * + * Created by minjaesong on 2026-04-06. + */ +object SplashScreen { + + private val stubParent = object : UICanvas() { + override var width = 0 + override var height = 0 + override fun updateImpl(delta: Float) {} + override fun renderImpl(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {} + override fun dispose() {} + } + + private var loadingBar: UIItemHorzSlider? = null + private var lastBarWidth = 0 + + private val subtitleCol = Color(0.75f, 0.75f, 0.75f, 1f) + + @JvmStatic + fun render(batch: SpriteBatch, camera: OrthographicCamera) { + val progress = CommonResourcePool.loadingProgress + val barWidth = (Toolkit.drawWidth * 0.4f).toInt().coerceAtLeast(200) + val barX = (Toolkit.drawWidth - barWidth) / 2 + val barY = App.scr.height - 48 + + if (loadingBar == null || lastBarWidth != barWidth) { + lastBarWidth = barWidth + loadingBar = UIItemHorzSlider(stubParent, barX, barY, 0.0, 0.0, 1.0, barWidth).also { + it.suppressHaptic = true + it.isEnabled = false + } + } + + val bar = loadingBar ?: return + bar.posX = barX + bar.posY = barY + bar.handleWidth = (progress * barWidth).toInt().coerceIn(12, barWidth) + + val subtitle = "${App.GAME_NAME} ${App.getVERSION_STRING()}" + val subtitleW = App.fontGame.getWidth(subtitle) + val subtitleX = (Toolkit.drawWidth - subtitleW) / 2f + val subtitleY = (barY - 20).toFloat() // leave gap above the bar + + batch.begin() + batch.color = subtitleCol + App.fontGame.draw(batch, subtitle, subtitleX, subtitleY) + batch.color = Color.WHITE + bar.render(0f, batch, camera) + batch.end() + } +} diff --git a/src/net/torvald/terrarum/ui/UIItemHorzSlider.kt b/src/net/torvald/terrarum/ui/UIItemHorzSlider.kt index 60e398313..af7a2c5a5 100644 --- a/src/net/torvald/terrarum/ui/UIItemHorzSlider.kt +++ b/src/net/torvald/terrarum/ui/UIItemHorzSlider.kt @@ -63,7 +63,7 @@ class UIItemHorzSlider( override fun update(delta: Float) { super.update(delta) - mouseOnHandle = itemRelativeMouseX in handlePos.roundToInt() until handlePos.roundToInt() + handleWidth && itemRelativeMouseY in 0 until height + mouseOnHandle = if (!isEnabled) false else itemRelativeMouseX in handlePos.roundToInt() until handlePos.roundToInt() + handleWidth && itemRelativeMouseY in 0 until height // update handle position and value if (mouseUp && Terrarum.mouseDown || mouseLatched) { diff --git a/src/net/torvald/terrarum/ui/UIItemVertSlider.kt b/src/net/torvald/terrarum/ui/UIItemVertSlider.kt index 5cccb0b6d..8b48685f1 100644 --- a/src/net/torvald/terrarum/ui/UIItemVertSlider.kt +++ b/src/net/torvald/terrarum/ui/UIItemVertSlider.kt @@ -60,7 +60,7 @@ class UIItemVertSlider( override fun update(delta: Float) { super.update(delta) - mouseOnHandle = itemRelativeMouseY in handlePos.roundToInt() until handlePos.roundToInt() + handleHeight && itemRelativeMouseX in 0 until width + mouseOnHandle = if (!isEnabled) false else itemRelativeMouseY in handlePos.roundToInt() until handlePos.roundToInt() + handleHeight && itemRelativeMouseX in 0 until width // update handle position and value if (mouseUp && Terrarum.mouseDown || mouseLatched) {