rendering: Improve TextField

This commit is contained in:
Bixilon 2021-04-26 20:50:29 +02:00
parent 0412be8d63
commit 6a74e2b6dd
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
9 changed files with 63 additions and 49 deletions

View File

@ -44,7 +44,7 @@ object KeyBindingsNames {
val OPEN_CHAT = ResourceLocation("minosoft:open_chat")
val CLOSE_CHAT = ResourceLocation("minosoft:close_chat")
val CLOSE = ResourceLocation("minosoft:close")
val SELECT_HOTBAR_SLOTS = arrayOf(
@ -194,10 +194,11 @@ object KeyBindingsNames {
KeyAction.PRESS to mutableSetOf(KeyCodes.KEY_T)
),
),
CLOSE_CHAT to KeyBinding(
CLOSE to KeyBinding(
mutableMapOf(
KeyAction.PRESS to mutableSetOf(KeyCodes.KEY_ESCAPE)
),
ignoreConsumer = true
),
)
}

View File

@ -257,4 +257,13 @@ class RenderWindowInputHandler(
fun unregisterKeyBinding(it: ResourceLocation) {
keyBindingCallbacks.remove(it)
}
fun isKeyDown(vararg keys: KeyCodes): Boolean {
for (key in keys) {
if (keysDown.contains(key)) {
return true
}
}
return false
}
}

View File

@ -72,6 +72,10 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
for ((_, element) in hudElements.values) {
element.init()
}
renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.CLOSE) {
}
}
private fun registerDefaultElements() {

View File

@ -17,7 +17,7 @@ import de.bixilon.minosoft.config.key.KeyCodes
interface KeyConsumer {
val focused: Boolean
fun close()
fun charInput(char: Char) {}

View File

@ -16,7 +16,6 @@ package de.bixilon.minosoft.gui.rendering.hud.elements.input
import glm_.vec2.Vec2i
interface MouseConsumer {
val focused: Boolean
fun mouseMove(position: Vec2i) {}
}

View File

@ -24,11 +24,9 @@ import glm_.vec2.Vec2i
open class TextField(
renderWindow: RenderWindow,
defaultText: String = "",
var maxLength: Int = 256,
val properties: TextFieldProperties,
) : AbsoluteLayout(renderWindow), KeyConsumer, MouseConsumer {
override var focused: Boolean = true
private var textBuilder: StringBuilder = StringBuilder(defaultText)
private var textBuilder: StringBuilder = StringBuilder(properties.defaultText)
val textElement = LabelNode(renderWindow, sizing = sizing, text = ChatComponent.valueOf(raw = text), background = false)
private var position = text.length
@ -57,7 +55,7 @@ open class TextField(
override fun keyInput(keyCodes: KeyCodes) {
when (keyCodes) {
KeyCodes.KEY_BACKSPACE -> {
if (textBuilder.isEmpty()) {
if (textBuilder.isEmpty() || position == 0) {
return
}
textBuilder.deleteCharAt(--position)
@ -69,10 +67,19 @@ open class TextField(
textBuilder.deleteCharAt(position)
}
KeyCodes.KEY_ENTER -> {
if (position > maxLength) {
if (renderWindow.inputHandler.isKeyDown(KeyCodes.KEY_LEFT_CONTROL, KeyCodes.KEY_RIGHT_CONTROL, KeyCodes.KEY_LEFT_SHIFT, KeyCodes.KEY_RIGHT_SHIFT)) {
// new line
if (position > properties.maxLength) {
return
}
textBuilder.insert(position++, '\n')
return
}
properties.onSubmit(text)
if (properties.submitCloses) {
properties.onClose()
}
text = properties.defaultText
}
KeyCodes.KEY_LEFT -> {
position = MMath.clamp(position - 1, 0, text.length)
@ -92,18 +99,28 @@ open class TextField(
}
override fun tick(tick: Long) {
if ((tick / 8) % 2L == 0L && position == text.length) {
if ((tick / FIELD_CURSOR_BLINK_INTERVAL) % 2L == 0L && position == text.length) {
textElement.sText = "$textBuilder" + "_"
} else {
textElement.sText = textBuilder.toString()
}
}
override fun close() {
properties.onClose()
}
override fun charInput(char: Char) {
if (position >= maxLength) {
if (position >= properties.maxLength) {
return
}
val previous = textBuilder.toString()
textBuilder.insert(position++, char.toString())
properties.onInput(previous, textBuilder.toString())
update()
}
companion object {
const val FIELD_CURSOR_BLINK_INTERVAL = 8
}
}

View File

@ -13,28 +13,11 @@
package de.bixilon.minosoft.gui.rendering.hud.elements.input
import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.gui.rendering.RenderWindow
class SubmittableTextField(
renderWindow: RenderWindow,
defaultText: String = "",
maxLength: Int = 256,
private val onSubmit: (text: String) -> Unit,
) : TextField(renderWindow, defaultText, maxLength) {
fun submit() {
onSubmit.invoke(text)
text = ""
}
override fun keyInput(keyCodes: KeyCodes) {
if (keyCodes == KeyCodes.KEY_ENTER) {
// submit
submit()
return
}
super.keyInput(keyCodes)
}
}
data class TextFieldProperties(
var defaultText: String = "",
var maxLength: Int = 256,
var onSubmit: (text: String) -> Unit = {},
var onClose: () -> Unit = {},
var onInput: (previousText: String, nextText: String) -> Unit = { _, _ -> },
var submitCloses: Boolean = false,
)

View File

@ -18,7 +18,8 @@ import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.elements.input.SubmittableTextField
import de.bixilon.minosoft.gui.rendering.hud.elements.input.TextField
import de.bixilon.minosoft.gui.rendering.hud.elements.input.TextFieldProperties
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.ImageNode
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
@ -28,14 +29,18 @@ import de.bixilon.minosoft.util.MMath
import glm_.vec2.Vec2i
class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer), ScreenResizeCallback {
private lateinit var inputField: SubmittableTextField
private lateinit var inputField: TextField
private var inputFieldBackground = ImageNode(hudRenderer.renderWindow, sizing = NodeSizing(margin = Spacing(left = 1, right = 1)), textureLike = hudRenderer.renderWindow.WHITE_TEXTURE, z = 0, tintColor = RenderConstants.TEXT_BACKGROUND_COLOR)
override fun init() {
inputField = SubmittableTextField(renderWindow = hudRenderer.renderWindow, maxLength = 256, onSubmit = {
hudRenderer.renderWindow.connection.sender.sendChatMessage(it)
closeChat()
})
inputField = TextField(
renderWindow = hudRenderer.renderWindow,
properties = TextFieldProperties(
maxLength = 256,
submitCloses = true,
onSubmit = { hudRenderer.renderWindow.connection.sender.sendChatMessage(it) },
onClose = { closeChat() },
))
layout.addChild(Vec2i(0, 0), inputField)
inputField.apply()
@ -43,9 +48,6 @@ class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer), Scr
hudRenderer.renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) {
openChat()
}
hudRenderer.renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.CLOSE_CHAT) {
closeChat()
}
}
override fun onScreenResize(screenDimensions: Vec2i) {
@ -63,7 +65,6 @@ class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer), Scr
fun closeChat() {
layout.removeChild(inputFieldBackground)
inputField.clearText()
hudRenderer.renderWindow.inputHandler.currentKeyConsumer = null
}
}

View File

@ -59,7 +59,7 @@ public class PacketSender {
if (this.connection.fireEvent(event)) {
return;
}
Log.log(LogMessageType.CHAT_OUT, "Sending chat message: %s", message);
Log.log(LogMessageType.CHAT_OUT, message);
this.connection.sendPacket(new ChatMessageC2SP(event.getMessage()));
}