mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-12 03:24:06 +09:00
212 lines
8.1 KiB
Kotlin
212 lines
8.1 KiB
Kotlin
package net.torvald.terrarum.ui
|
|
|
|
import com.badlogic.gdx.graphics.OrthographicCamera
|
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|
import net.torvald.terrarum.App
|
|
import net.torvald.terrarum.CommonResourcePool
|
|
import net.torvald.terrarum.Terrarum
|
|
import net.torvald.terrarum.ceilToInt
|
|
import kotlin.math.absoluteValue
|
|
|
|
/**
|
|
* Internal properties, namely initialValue, min, max, step; have the type of [Double] regardless of their input type.
|
|
*
|
|
* Created by minjaesong on 2021-10-23.
|
|
*/
|
|
|
|
class UIItemSpinner(
|
|
parentUI: UICanvas,
|
|
initialX: Int, initialY: Int,
|
|
private var initialValue: Number,
|
|
val min: Number,
|
|
val max: Number,
|
|
val step: Number,
|
|
override val width: Int,
|
|
private val drawBorder: Boolean = true,
|
|
private val numberToTextFunction: (Number) -> String = { "$it" }
|
|
) : UIItem(parentUI, initialX, initialY) {
|
|
|
|
// to alleviate floating point errors adding up as the spinner is being used
|
|
private val values = DoubleArray(1 + ((max.toDouble() - min.toDouble()).div(step.toDouble())).ceilToInt()) {
|
|
// printdbg(this, "$min..$max step $step; index [$it] = ${min.toDouble() + (step.toDouble() * it)}")
|
|
min.toDouble() + (step.toDouble() * it)
|
|
}
|
|
|
|
init {
|
|
// println("valueType=${valueType.canonicalName} for UI ${parentUI.javaClass.canonicalName}")
|
|
|
|
resetToInitial()
|
|
}
|
|
|
|
private val valueType = initialValue.javaClass // should be java.lang.Double or java.lang.Integer
|
|
|
|
private val labels = CommonResourcePool.getAsTextureRegionPack("inventory_category")
|
|
|
|
override val height = 24
|
|
private val buttonW = 30
|
|
|
|
private val fboWidth = width - 2*buttonW - 6
|
|
private val fboHeight = height - 4
|
|
// private val fbo = FrameBuffer(Pixmap.Format.RGBA8888, width - 2*buttonW - 6, height - 4, false)
|
|
|
|
var value = initialValue.toDouble().coerceIn(min.toDouble(), max.toDouble()) as Number; private set
|
|
var fboUpdateLatch = true
|
|
|
|
private var mouseOnButton = 0 // 0: nothing, 1: left, 2: right
|
|
|
|
var selectionChangeListener: (Number) -> Unit = {}
|
|
private var currentIndex = values.indexOfFirst { it == initialValue.toDouble() }
|
|
|
|
fun resetToInitial() {
|
|
// if the initial value cannot be derived from the settings, round to nearest
|
|
if (values.indexOfFirst { it == initialValue.toDouble() } < 0) {
|
|
// throw IllegalArgumentException("Initial value $initialValue cannot be derived from given ($min..$max step $step) settings")
|
|
val mind = min.toDouble()
|
|
val maxd = max.toDouble()
|
|
val stepd = step.toDouble()
|
|
val id = initialValue.toDouble()
|
|
|
|
val intermediate = (0..(maxd - mind).div(stepd).ceilToInt()).map {
|
|
it to ((mind + stepd * it) - id).absoluteValue
|
|
}.minBy { it.second }.first * stepd + mind
|
|
initialValue = when (initialValue.javaClass.simpleName) {
|
|
"Integer" -> intermediate.toInt()
|
|
else -> intermediate
|
|
}
|
|
}
|
|
fboUpdateLatch = true
|
|
}
|
|
|
|
fun resetToSmallest() {
|
|
currentIndex = 0
|
|
value = values[currentIndex]
|
|
fboUpdateLatch = true
|
|
}
|
|
|
|
fun changeValueBy(diff: Int) {
|
|
currentIndex = (currentIndex + diff).coerceIn(values.indices)
|
|
value = values[currentIndex]
|
|
}
|
|
|
|
override fun update(delta: Float) {
|
|
super.update(delta)
|
|
|
|
mouseOnButton =
|
|
if (itemRelativeMouseX in 0 until buttonW && itemRelativeMouseY in 0 until height)
|
|
1
|
|
else if (itemRelativeMouseX in width - buttonW until width && itemRelativeMouseY in 0 until height)
|
|
2
|
|
else if (itemRelativeMouseX in buttonW + 3 until width - buttonW - 3 && itemRelativeMouseY in 0 until height)
|
|
3
|
|
else
|
|
0
|
|
|
|
if (mouseOnButton in 1..2) mouseLatch.latch {
|
|
changeValueBy((mouseOnButton * 2) - 3)
|
|
fboUpdateLatch = true
|
|
selectionChangeListener(value)
|
|
}
|
|
}
|
|
|
|
private var textCache = ""
|
|
private var textCacheLen = 0
|
|
|
|
override fun show() {
|
|
fboUpdateLatch = true
|
|
}
|
|
|
|
override fun render(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {
|
|
|
|
batch.end()
|
|
|
|
if (fboUpdateLatch) {
|
|
// printdbg(this, "FBO Latched")
|
|
fboUpdateLatch = false
|
|
textCache = numberToTextFunction(value.toDouble() + 0.0000000000000002)
|
|
textCacheLen = App.fontGame.getWidth(textCache)
|
|
/*fbo.inAction(camera as OrthographicCamera, batch) { batch.inUse {
|
|
gdxClearAndSetBlend(0f, 0f, 0f, 0f)
|
|
|
|
it.color = Color.WHITE
|
|
val t = numberToTextFunction(value)
|
|
val tw = App.fontGame.getWidth(t)
|
|
App.fontGameFBO.draw(it, t, (fbo.width - tw) / 2, 0)
|
|
} }*/
|
|
}
|
|
|
|
batch.begin()
|
|
|
|
if (drawBorder) {
|
|
batch.color = UIItemTextLineInput.TEXTINPUT_COL_BACKGROUND
|
|
// left button cell back
|
|
Toolkit.fillArea(batch, posX, posY, buttonW, height)
|
|
// text area cell back
|
|
Toolkit.fillArea(batch, posX + buttonW + 3, posY, width - 2*buttonW - 6, height)
|
|
// right button cell back
|
|
Toolkit.fillArea(batch, posX + width - buttonW, posY, buttonW, height)
|
|
|
|
// text area border
|
|
if (mouseOnButton != 3) {
|
|
batch.color = Toolkit.Theme.COL_INACTIVE
|
|
Toolkit.drawBoxBorder(batch, posX - 1, posY - 1, width + 2, height + 2)
|
|
}
|
|
|
|
// left button border
|
|
batch.color = if (mouseOnButton == 1 && mousePushed) Toolkit.Theme.COL_SELECTED
|
|
else if (mouseOnButton == 1) Toolkit.Theme.COL_MOUSE_UP else Toolkit.Theme.COL_INACTIVE
|
|
Toolkit.drawBoxBorder(batch, posX - 1, posY - 1, buttonW + 2, height + 2)
|
|
|
|
// right button border
|
|
batch.color = if (mouseOnButton == 2 && mousePushed) Toolkit.Theme.COL_SELECTED
|
|
else if (mouseOnButton == 2) Toolkit.Theme.COL_MOUSE_UP else Toolkit.Theme.COL_INACTIVE
|
|
Toolkit.drawBoxBorder(batch, posX + width - buttonW - 1, posY - 1, buttonW + 2, height + 2)
|
|
|
|
// text area border (again)
|
|
if (mouseOnButton == 3) {
|
|
batch.color = Toolkit.Theme.COL_MOUSE_UP
|
|
Toolkit.drawBoxBorder(batch, posX + buttonW + 2, posY - 1, width - 2*buttonW - 4, height + 2)
|
|
}
|
|
}
|
|
|
|
// left button icon
|
|
batch.color = if (mouseOnButton == 1 && mousePushed) Toolkit.Theme.COL_SELECTED
|
|
else if (mouseOnButton == 1) Toolkit.Theme.COL_MOUSE_UP else UIItemTextLineInput.TEXTINPUT_COL_TEXT
|
|
batch.draw(labels.get(9,2), posX + (buttonW - labels.tileW) / 2f, posY + (height - labels.tileH) / 2f)
|
|
|
|
// right button icon
|
|
batch.color = if (mouseOnButton == 2 && mousePushed) Toolkit.Theme.COL_SELECTED
|
|
else if (mouseOnButton == 2) Toolkit.Theme.COL_MOUSE_UP else UIItemTextLineInput.TEXTINPUT_COL_TEXT
|
|
batch.draw(labels.get(10,2), posX + width - buttonW + (buttonW - labels.tileW) / 2f, posY + (height - labels.tileH) / 2f)
|
|
|
|
// draw text
|
|
batch.color = UIItemTextLineInput.TEXTINPUT_COL_TEXT
|
|
// batch.draw(fbo.colorBufferTexture, posX + buttonW + 3f, posY + 2f, fbo.width.toFloat(), fbo.height.toFloat())
|
|
App.fontGame.draw(batch, textCache, posX + buttonW + 3f + (fboWidth - textCacheLen).div(2), posY.toFloat())
|
|
|
|
super.render(frameDelta, batch, camera)
|
|
|
|
// batch.color = Color.WHITE
|
|
// App.fontSmallNumbers.draw(batch, "${valueType.simpleName}", posX.toFloat(), posY.toFloat()) // draws "Integer" or "Double"
|
|
}
|
|
|
|
override fun scrolled(amountX: Float, amountY: Float): Boolean {
|
|
if (mouseUp) {
|
|
if (amountX <= -1 || amountY <= -1)
|
|
changeValueBy(-1)
|
|
else if (amountX >= 1 || amountY >= 1)
|
|
changeValueBy(1)
|
|
|
|
selectionChangeListener(value)
|
|
fboUpdateLatch = true
|
|
return true
|
|
}
|
|
else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
override fun dispose() {
|
|
// fbo.dispose()
|
|
}
|
|
}
|