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.g2d.SpriteBatch import net.torvald.EMDASH import net.torvald.terrarum.App 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.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(MESSAGES_MAX, true) private var messageDisplayPos: Int = 0 private var messagesCount: Int = 0 // private var commandInputPool: StringBuilder? = null private var commandHistory = CircularArray(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) private var clickLatched = false init { reset() addUIitem(textinput) textinput.isActive = false } private val lb = ArrayList() override fun updateUI(delta: Float) { Terrarum.ingame?.let { if (Authenticator.b()) { lb.clear() val actorsUnderCursor = it.getActorsAt(Terrarum.mouseX, Terrarum.mouseY) actorsUnderCursor.forEach { lb.add("${it.referenceID} (${it.actorValue[AVKey.NAME] ?: "\u03AF-${it.javaClass.simpleName}"})") } it.setTooltipMessage(if (lb.size > 0) lb.joinToString("\n") else null) // 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 { it.setTooltipMessage(null) } } uiItems.forEach { it.update(delta) } if (!Gdx.input.isButtonPressed(App.getConfigInt("config_mouseprimary"))) { clickLatched = false } } override fun renderUI(batch: SpriteBatch, camera: Camera) { // 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(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] ConcurrentModificationException") } 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(MESSAGES_MAX, true) messageDisplayPos = 0 messagesCount = 0 inputCursorPos = 0 commandHistory = CircularArray(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 { println("Game was paused beforehand: ${it.paused}") if (!it.paused) { iMadeTheGameToPause = true it.pause() } else { iMadeTheGameToPause = false } println("I made the game to pause: $iMadeTheGameToPause") } /*openingTimeCounter += delta drawOffY = MovementInterpolator.fastPullOut(openingTimeCounter.toFloat() / openCloseTime.toFloat(), -height.toFloat(), 0f )*/ } override fun doClosing(delta: Float) { /*openingTimeCounter += delta drawOffY = MovementInterpolator.fastPullOut(openingTimeCounter.toFloat() / openCloseTime.toFloat(), 0f, -height.toFloat() )*/ textinput.isActive = false textinput.mouseoverUpdateLatch = false } override fun endOpening(delta: Float) { drawOffY = 0f openingTimeCounter = 0f textinput.isActive = true textinput.mouseoverUpdateLatch = true } override fun endClosing(delta: Float) { Terrarum.ingame?.setTooltipMessage(null) println("Close -- I made the game to pause: $iMadeTheGameToPause") if (iMadeTheGameToPause) { Terrarum.ingame?.resume() println("Close -- resume game") } drawOffY = -height.toFloat() openingTimeCounter = 0f iMadeTheGameToPause = false } override fun dispose() { uiItems.forEach { it.dispose() } } }