package net.torvald.terrarum.modulebasegame.ui import com.badlogic.gdx.Gdx import com.badlogic.gdx.Input import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.g2d.SpriteBatch import net.torvald.terrarum.App import net.torvald.terrarum.CommonResourcePool import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.ui.* import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack typealias ControlPanelOptions = Array> /** * Created by minjaesong on 2023-07-14. */ object ControlPanelCommon { init { CommonResourcePool.addToLoadingList("gui_hrule") { TextureRegionPack(Gdx.files.internal("assets/graphics/gui/hrule.tga"), 216, 20) } CommonResourcePool.loadAll() } var CONFIG_SPINNER_WIDTH = 140 var CONFIG_TYPEIN_WIDTH = 240 var CONFIG_SLIDER_WIDTH = 240 var CONFIG_TEXTSEL_WIDTH = 240 // @return Pair of fun makeButton(parent: UICanvas, args: String, x: Int, y: Int, optionNames0: String): Pair Unit> { val optionNames = optionNames0.split(",") val optionName = optionNames.first() val arg = args.split(',') return if (args.equals("h1") || args.equals("p")) { (object : UIItem(parent, x, y) { override val width = 1 override val height = 1 override fun dispose() {} }) to { _, _ -> } } else if (args.startsWith("toggle")) { UIItemToggleButton(parent, x, y, CONFIG_SPINNER_WIDTH, App.getConfigBoolean(optionName)) to { it: UIItem, optionStr: String -> (it as UIItemToggleButton).clickOnceListener = { _, _ -> it.toggle() App.setConfig(optionStr, it.getStatus()) } } } else if (args.startsWith("textsel,")) { val labelFuns = arg.subList(1, arg.size).map { { Lang[it.substringAfter("=")] } } val optionsList = arg.subList(1, arg.size).map { it.substringBefore("=") } val initialSel = optionsList.indexOf(App.getConfigString(optionName)) // println("labelFuns = ${labelFuns.map { it.invoke() }}") // println("optionsList = $optionsList") // println("optionName = $optionName; value = ${App.getConfigString(optionName)}") // println("initialSel = $initialSel") if (initialSel < 0) throw IllegalArgumentException("config value '${App.getConfigString(optionName)}' for option '$optionName' is not found on the options list") UIItemTextSelector(parent, x, y, labelFuns, initialSel, CONFIG_TEXTSEL_WIDTH, clickToShowPalette = false) to { it: UIItem, optionStr: String -> (it as UIItemTextSelector).selectionChangeListener = { App.setConfig(optionStr, optionsList[it]) } } } else if (args.startsWith("spinnersel,")) { val labelFuns = arg.subList(1, arg.size).map { { it } } val optionsList = arg.subList(1, arg.size).map { it.toInt() } val initialSel = optionsList.indexOf(App.getConfigInt(optionName)) if (initialSel < 0) throw IllegalArgumentException("config value '${App.getConfigInt(optionName)}' for option '$optionName' is not found on the options list") UIItemTextSelector(parent, x, y, labelFuns, initialSel, CONFIG_SPINNER_WIDTH, clickToShowPalette = false, useSpinnerButtons = true) to { it: UIItem, optionStr: String -> (it as UIItemTextSelector).selectionChangeListener = { App.setConfig(optionStr, optionsList[it]) } } } else if (args.startsWith("spinner,")) { UIItemSpinner(parent, x, y, App.getConfigInt(optionName), arg[1].toInt(), arg[2].toInt(), arg[3].toInt(), CONFIG_SPINNER_WIDTH, numberToTextFunction = { "${it.toLong()}" }) to { it: UIItem, optionStr: String -> (it as UIItemSpinner).selectionChangeListener = { App.setConfig(optionStr, it) } } } else if (args.startsWith("spinnerd,")) { UIItemSpinner(parent, x, y, App.getConfigDouble(optionName), arg[1].toDouble(), arg[2].toDouble(), arg[3].toDouble(), CONFIG_SPINNER_WIDTH, numberToTextFunction = { "${((it as Double)*100).toInt()}%" }) to { it: UIItem, optionStr: String -> (it as UIItemSpinner).selectionChangeListener = { App.setConfig(optionStr, it) } } } else if (args.startsWith("sliderd,")) { UIItemHorzSlider(parent, x, y, App.getConfigDouble(optionName), arg[1].toDouble(), arg[2].toDouble(), CONFIG_SLIDER_WIDTH) to { it: UIItem, optionStr: String -> (it as UIItemHorzSlider).selectionChangeListener = { App.setConfig(optionStr, it) } } } else if (args.startsWith("spinnerimul,")) { val mult = arg[4].toInt() UIItemSpinner(parent, x, y, App.getConfigInt(optionName) / mult, arg[1].toInt(), arg[2].toInt(), arg[3].toInt(), CONFIG_SPINNER_WIDTH, numberToTextFunction = { "${it.toLong()}" }) to { it: UIItem, optionStr: String -> (it as UIItemSpinner).selectionChangeListener = { App.setConfig(optionStr, it.toInt() * mult) } } } else if (args.startsWith("typeinint")) { // val arg = args.split(',') // args: none UIItemTextLineInput(parent, x, y, CONFIG_SPINNER_WIDTH, defaultValue = { "${App.getConfigInt(optionName)}" }, maxLen = InputLenCap(4, InputLenCap.CharLenUnit.CODEPOINTS), keyFilter = { it.headkey in Input.Keys.NUM_0..Input.Keys.NUM_9 || it.headkey == Input.Keys.BACKSPACE } ) to { it: UIItem, optionStr: String -> (it as UIItemTextLineInput).textCommitListener = { App.setConfig(optionStr, it.toInt()) // HAXXX!!! } } } else if (args.startsWith("typeinres")) { val keyWidth = optionNames[0] val keyHeight = optionNames[1] UIItemTextLineInput(parent, x, y, CONFIG_SPINNER_WIDTH, defaultValue = { "${App.getConfigInt(keyWidth)}x${App.getConfigInt(keyHeight)}" }, maxLen = InputLenCap(9, InputLenCap.CharLenUnit.CODEPOINTS), keyFilter = { it.headkey == Input.Keys.ENTER || it.headkey == Input.Keys.BACKSPACE || it.character?.matches(Regex("[0-9xX]")) == true }, alignment = UIItemTextButton.Companion.Alignment.CENTRE ) to { it: UIItem, optionStr: String -> (it as UIItemTextLineInput).textCommitListener = { text -> val text = text.lowercase() if (text.matches(Regex("""[0-9]+x[0-9]+"""))) { it.markAsNormal() val width = text.substringBefore('x').toInt() val height = text.substringAfter('x').toInt() App.setConfig(keyWidth, width) App.setConfig(keyHeight, height) } else it.markAsInvalid() } } } else if (args.startsWith("typein")) { //args: none UIItemTextLineInput(parent, x, y, CONFIG_TYPEIN_WIDTH, defaultValue = { App.getConfigString(optionName) }) to { it: UIItem, optionStr: String -> (it as UIItemTextLineInput).textCommitListener = { App.setConfig(optionStr, it) } } } else throw IllegalArgumentException(args) } private val linegap = 14 private val panelgap = 20 private val rowheight = 20 + linegap private val h1MarginTop = 16 private val h1MarginBottom = 4 private val optionsYposCache = HashMap() private val optionsCache = HashMap() fun register(ui: UICanvas, width: Int, identifier: String, options: ControlPanelOptions) { optionsCache[identifier] = options val optionsYpos = IntArray(options.size + 1) var akku = 0 options.forEachIndexed { index, row -> val option = row[2] if (index > 0 && option == "h1") { akku += h1MarginTop } optionsYpos[index] = akku akku += when (option) { "h1" -> rowheight + h1MarginBottom else -> rowheight } } optionsYpos[optionsYpos.lastIndex] = akku optionsYposCache[identifier] = optionsYpos val height = optionsYpos.last() val drawX = (App.scr.width - width) / 2 val drawY = (App.scr.height - height) / 2 options.forEachIndexed { index, args -> val (item, job) = makeButton( ui, args[2] as String, drawX + width / 2 + panelgap, drawY - 2 + optionsYpos[index], args[0] as String ) job.invoke(item, args[0] as String) ui.addUIitem(item) } } private val hrule = CommonResourcePool.getAsTextureRegionPack("gui_hrule") fun getMenuHeight(identifier: String) = optionsYposCache[identifier]!!.last() fun render(identifier: String, width: Int, batch: SpriteBatch) { val height = optionsYposCache[identifier]!!.last() val drawX = (App.scr.width - width) / 2 val drawY = (App.scr.height - height) / 2 val optionsYpos = optionsYposCache[identifier]!! optionsCache[identifier]!!.forEachIndexed { index, args -> val mode = args[2] val font = if (mode == "h1") App.fontUITitle else App.fontGame val label = (args[1] as () -> String).invoke() val labelWidth = font.getWidth(label) batch.color = when (mode) { "h1" -> Toolkit.Theme.COL_MOUSE_UP "p" -> Color.LIGHT_GRAY else -> Color.WHITE } val xpos = if (mode == "p" || mode == "h1") drawX + (width - labelWidth)/2 // centre-aligned else drawX + width/2 - panelgap - labelWidth // right aligned at the middle of the panel, offsetted by panelgap font.draw(batch, label, xpos.toFloat(), drawY + optionsYpos[index] - 2f) // draw hrule if (mode == "h1") { val ruleWidth = ((width - 24 - labelWidth) / 2).toFloat() batch.draw(hrule.get(0,0), xpos - 24f - ruleWidth, drawY + optionsYpos[index].toFloat(), ruleWidth, hrule.tileH.toFloat()) batch.draw(hrule.get(0,1), xpos + 24f + labelWidth, drawY + optionsYpos[index].toFloat(), ruleWidth, hrule.tileH.toFloat()) } } } }