Files
Terrarum/src/net/torvald/terrarum/ui/ConsoleWindow.kt
2024-10-12 11:26:29 +09:00

309 lines
10 KiB
Kotlin

package net.torvald.terrarum.ui
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.TerrarumAppConfiguration
import net.torvald.terrarum.ccE
import net.torvald.terrarum.console.Authenticator
import net.torvald.terrarum.console.CommandInterpreter
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
import net.torvald.terrarum.langpack.Lang
import net.torvald.unicode.EMDASH
import net.torvald.util.CircularArray
/**
* Don't let the debug console have the ```toggleKeyLiteral```, this must open even when the game is paused
*
* Created by minjaesong on 2015-12-31.
*/
class ConsoleWindow : UICanvas() {
internal var UIColour = Color(0x404080_80.toInt())
private var inputCursorPos: Int = 0
private val MESSAGES_MAX = 1000
private val COMMAND_HISTORY_MAX = 100
private var messages = CircularArray<String>(MESSAGES_MAX, true)
private var messageDisplayPos: Int = 0
private var messagesCount: Int = 0
// private var commandInputPool: StringBuilder? = null
private var commandHistory = CircularArray<String>(COMMAND_HISTORY_MAX, true)
private val LINE_HEIGHT = 20
private val MESSAGES_DISPLAY_COUNT = 11
private val inputToMsgboxGap = 3
override var width: Int = App.scr.width
override var height: Int = LINE_HEIGHT * (MESSAGES_DISPLAY_COUNT + 1) + inputToMsgboxGap
override var openCloseTime = 0f
private var drawOffX: Float = 0f
private var drawOffY: Float = -height.toFloat()
private var openingTimeCounter = 0f
private var historyIndex = -1
private var iMadeTheGameToPause = false
private val textinput = UIItemTextLineInput(this, 0, 0, this.width, keyFilter = { e ->
!e.keycodes.contains(Input.Keys.GRAVE)
})
private var clickLatched = false
init {
reset()
addUIitem(textinput)
textinput.isEnabled = false
}
private val lb = ArrayList<String>()
override fun updateImpl(delta: Float) {
Terrarum.ingame?.let {
if (Authenticator.b()) {
lb.clear()
val actorsUnderCursor = it.getActorsAt(Terrarum.mouseX, Terrarum.mouseY)
actorsUnderCursor.filter { it.referenceID < 2147483647 }.forEach { // filter out the BlockMarkerActor
lb.add("${it.referenceID} (${it.actorValue[AVKey.NAME] ?: "\u03AF-${it.javaClass.simpleName}"})")
}
if (lb.size > 0)
acquireTooltip(lb.joinToString("\n"))
else
releaseTooltip()
// click to enter the actor's reference ID
if (lb.size > 0 && !clickLatched && Gdx.input.isButtonPressed(App.getConfigInt("config_mouseprimary"))) {
clickLatched = true
textinput.appendText(lb.first().substringBefore(' '))
}
}
else {
releaseTooltip()
}
}
uiItems.forEach { it.update(delta) }
if (!Gdx.input.isButtonPressed(App.getConfigInt("config_mouseprimary"))) {
clickLatched = false
}
textinput.isEnabled = (isOpened && !isClosing)
}
override fun renderImpl(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {
posY = App.scr.tvSafeActionHeight // move away from the top area
// background
batch.color = UIColour
Toolkit.fillArea(batch, drawOffX, drawOffY, width.toFloat(), height.toFloat())
Toolkit.fillArea(batch, drawOffX, drawOffY, width.toFloat(), LINE_HEIGHT.toFloat())
// val input = commandInputPool!!.toString()
// val inputDrawWidth = App.fontGame.getWidth(input)
// val inputDrawHeight = App.fontGame.lineHeight
//
// text and cursor
// batch.color = Color.WHITE
// App.fontGame.draw(batch, input, 1f + drawOffX, drawOffY)
//
// batch.color = Color(0x7f7f7f_ff)
// Toolkit.fillArea(batch, inputDrawWidth.toFloat() + drawOffX + 1, drawOffY, 2f, inputDrawHeight)
// batch.color = Color.WHITE
// Toolkit.fillArea(batch, inputDrawWidth.toFloat() + drawOffX + 1, drawOffY, 1f, inputDrawHeight - 1)
// messages
batch.color = Color.WHITE
for (i in 0 until MESSAGES_DISPLAY_COUNT) {
val message = messages[messageDisplayPos + i] ?: ""
App.fontGame.draw(batch, message, 1f + drawOffX, (LINE_HEIGHT * (MESSAGES_DISPLAY_COUNT - i)).toFloat() + drawOffY + inputToMsgboxGap)
}
uiItems.forEach { it.render(frameDelta, batch, camera) }
}
override fun inputStrobed(e: TerrarumKeyboardEvent) {
uiItems.forEach { it.inputStrobed(e) }
}
override fun keyDown(key: Int): Boolean {
try {
val textOnBuffer = textinput.getText()
// history
if (key == Input.Keys.UP && historyIndex < commandHistory.elemCount)
historyIndex++
else if (key == Input.Keys.DOWN && historyIndex >= 0)
historyIndex--
else if (key != Input.Keys.UP && key != Input.Keys.DOWN)
historyIndex = -1
// execute
if (key == Input.Keys.ENTER && textOnBuffer.isNotEmpty()) {
commandHistory.appendHead(textOnBuffer)
executeCommand(textOnBuffer)
textinput.clearText()
}
// scroll
else if (key == Input.Keys.UP || key == Input.Keys.DOWN) {
// create new stringbuilder
textinput.clearText()
if (historyIndex >= 0) // just leave blank if index is -1
textinput.setText(commandHistory[historyIndex] ?: "")
}
// delete input
// else if (key == Input.Keys.BACKSPACE) {
// commandInputPool = StringBuilder()
// }
// message scroll up
else if (key == Input.Keys.PAGE_UP) {
setDisplayPos(-MESSAGES_DISPLAY_COUNT + 1)
}
// message scroll down
else if (key == Input.Keys.PAGE_DOWN) {
setDisplayPos(MESSAGES_DISPLAY_COUNT - 1)
}
}
catch (e: ConcurrentModificationException) {
System.err.println("[ConsoleWindow.keyDown] ConcurrentModificationException with key ${Input.Keys.toString(key)}")
}
return true
}
val acceptedChars = "1234567890-=qwfpgjluy;[]\\arstdhneio'zxcvbkm,./!@#$%^&*()_+QWFPGJLUY:{}|ARSTDHNEIO\"ZXCVBKM<>? ".toSet()
/*override fun keyTyped(character: Char): Boolean {
if (character in acceptedChars) {
commandInputPool!!.append(character)
inputCursorPos += 1
return true
}
else {
return false
}
}*/
override fun keyUp(keycode: Int): Boolean {
return false
}
private fun executeCommand(s: String) {
CommandInterpreter.execute(s)
}
fun sendMessage(msg: String) {
messages.appendHead(msg)
messagesCount += 1
}
private fun setDisplayPos(change: Int) {
val lowLim = 0
val highLim = if (messagesCount <= MESSAGES_DISPLAY_COUNT)
0
else
messagesCount - MESSAGES_DISPLAY_COUNT
val newVal = messageDisplayPos + change
if (newVal < lowLim) {
messageDisplayPos = lowLim
}
else if (newVal > highLim) {
messageDisplayPos = highLim
}
else {
messageDisplayPos = newVal
}
}
fun reset() {
messages = CircularArray<String>(MESSAGES_MAX, true)
messageDisplayPos = 0
messagesCount = 0
inputCursorPos = 0
commandHistory = CircularArray<String>(COMMAND_HISTORY_MAX, true)
textinput.clearText()
if (Authenticator.b()) {
sendMessage("$ccE${TerrarumAppConfiguration.GAME_NAME} ${App.getVERSION_STRING()} $EMDASH ${TerrarumAppConfiguration.COPYRIGHT_DATE_NAME}")
sendMessage("$ccE${TerrarumAppConfiguration.COPYRIGHT_LICENSE}")
sendMessage(Lang["DEV_MESSAGE_CONSOLE_CODEX"])
}
}
override fun doOpening(delta: Float) {
Terrarum.ingame?.let {
// printdbg(this, "Game was paused beforehand: ${it.paused}")
if (!it.paused) {
iMadeTheGameToPause = true
it.pause()
}
else {
iMadeTheGameToPause = false
}
// printdbg(this, "I made the game to pause: $iMadeTheGameToPause")
}
/*openingTimeCounter += delta
drawOffY = MovementInterpolator.fastPullOut(openingTimeCounter.toFloat() / openCloseTime.toFloat(),
-height.toFloat(), 0f
)*/
clearTooltip()
}
override fun doClosing(delta: Float) {
/*openingTimeCounter += delta
drawOffY = MovementInterpolator.fastPullOut(openingTimeCounter.toFloat() / openCloseTime.toFloat(),
0f, -height.toFloat()
)*/
textinput.isEnabled = false
textinput.mouseoverUpdateLatch = false
clearTooltip()
}
override fun endOpening(delta: Float) {
drawOffY = 0f
openingTimeCounter = 0f
textinput.isEnabled = true
textinput.mouseoverUpdateLatch = true
clearTooltip()
}
override fun endClosing(delta: Float) {
// printdbg(this, "Close -- I made the game to pause: $iMadeTheGameToPause")
if (iMadeTheGameToPause) {
Terrarum.ingame?.resume()
// printdbg(this, "Close -- resume game")
}
iMadeTheGameToPause = false
clearTooltip()
drawOffY = -height.toFloat()
openingTimeCounter = 0f
}
override fun dispose() {
uiItems.forEach { it.dispose() }
}
}