mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-19 04:15:14 -04:00
rendering: Improve TextField
This commit is contained in:
parent
0412be8d63
commit
6a74e2b6dd
@ -44,7 +44,7 @@ object KeyBindingsNames {
|
|||||||
|
|
||||||
val OPEN_CHAT = ResourceLocation("minosoft:open_chat")
|
val OPEN_CHAT = ResourceLocation("minosoft:open_chat")
|
||||||
|
|
||||||
val CLOSE_CHAT = ResourceLocation("minosoft:close_chat")
|
val CLOSE = ResourceLocation("minosoft:close")
|
||||||
|
|
||||||
|
|
||||||
val SELECT_HOTBAR_SLOTS = arrayOf(
|
val SELECT_HOTBAR_SLOTS = arrayOf(
|
||||||
@ -194,10 +194,11 @@ object KeyBindingsNames {
|
|||||||
KeyAction.PRESS to mutableSetOf(KeyCodes.KEY_T)
|
KeyAction.PRESS to mutableSetOf(KeyCodes.KEY_T)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
CLOSE_CHAT to KeyBinding(
|
CLOSE to KeyBinding(
|
||||||
mutableMapOf(
|
mutableMapOf(
|
||||||
KeyAction.PRESS to mutableSetOf(KeyCodes.KEY_ESCAPE)
|
KeyAction.PRESS to mutableSetOf(KeyCodes.KEY_ESCAPE)
|
||||||
),
|
),
|
||||||
|
ignoreConsumer = true
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -257,4 +257,13 @@ class RenderWindowInputHandler(
|
|||||||
fun unregisterKeyBinding(it: ResourceLocation) {
|
fun unregisterKeyBinding(it: ResourceLocation) {
|
||||||
keyBindingCallbacks.remove(it)
|
keyBindingCallbacks.remove(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isKeyDown(vararg keys: KeyCodes): Boolean {
|
||||||
|
for (key in keys) {
|
||||||
|
if (keysDown.contains(key)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,10 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
|
|||||||
for ((_, element) in hudElements.values) {
|
for ((_, element) in hudElements.values) {
|
||||||
element.init()
|
element.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.CLOSE) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerDefaultElements() {
|
private fun registerDefaultElements() {
|
||||||
|
@ -17,7 +17,7 @@ import de.bixilon.minosoft.config.key.KeyCodes
|
|||||||
|
|
||||||
interface KeyConsumer {
|
interface KeyConsumer {
|
||||||
|
|
||||||
val focused: Boolean
|
fun close()
|
||||||
|
|
||||||
fun charInput(char: Char) {}
|
fun charInput(char: Char) {}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ package de.bixilon.minosoft.gui.rendering.hud.elements.input
|
|||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
interface MouseConsumer {
|
interface MouseConsumer {
|
||||||
val focused: Boolean
|
|
||||||
|
|
||||||
fun mouseMove(position: Vec2i) {}
|
fun mouseMove(position: Vec2i) {}
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,9 @@ import glm_.vec2.Vec2i
|
|||||||
|
|
||||||
open class TextField(
|
open class TextField(
|
||||||
renderWindow: RenderWindow,
|
renderWindow: RenderWindow,
|
||||||
defaultText: String = "",
|
val properties: TextFieldProperties,
|
||||||
var maxLength: Int = 256,
|
|
||||||
) : AbsoluteLayout(renderWindow), KeyConsumer, MouseConsumer {
|
) : AbsoluteLayout(renderWindow), KeyConsumer, MouseConsumer {
|
||||||
override var focused: Boolean = true
|
private var textBuilder: StringBuilder = StringBuilder(properties.defaultText)
|
||||||
private var textBuilder: StringBuilder = StringBuilder(defaultText)
|
|
||||||
val textElement = LabelNode(renderWindow, sizing = sizing, text = ChatComponent.valueOf(raw = text), background = false)
|
val textElement = LabelNode(renderWindow, sizing = sizing, text = ChatComponent.valueOf(raw = text), background = false)
|
||||||
private var position = text.length
|
private var position = text.length
|
||||||
|
|
||||||
@ -57,7 +55,7 @@ open class TextField(
|
|||||||
override fun keyInput(keyCodes: KeyCodes) {
|
override fun keyInput(keyCodes: KeyCodes) {
|
||||||
when (keyCodes) {
|
when (keyCodes) {
|
||||||
KeyCodes.KEY_BACKSPACE -> {
|
KeyCodes.KEY_BACKSPACE -> {
|
||||||
if (textBuilder.isEmpty()) {
|
if (textBuilder.isEmpty() || position == 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
textBuilder.deleteCharAt(--position)
|
textBuilder.deleteCharAt(--position)
|
||||||
@ -69,10 +67,19 @@ open class TextField(
|
|||||||
textBuilder.deleteCharAt(position)
|
textBuilder.deleteCharAt(position)
|
||||||
}
|
}
|
||||||
KeyCodes.KEY_ENTER -> {
|
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
|
return
|
||||||
}
|
}
|
||||||
textBuilder.insert(position++, '\n')
|
properties.onSubmit(text)
|
||||||
|
if (properties.submitCloses) {
|
||||||
|
properties.onClose()
|
||||||
|
}
|
||||||
|
text = properties.defaultText
|
||||||
}
|
}
|
||||||
KeyCodes.KEY_LEFT -> {
|
KeyCodes.KEY_LEFT -> {
|
||||||
position = MMath.clamp(position - 1, 0, text.length)
|
position = MMath.clamp(position - 1, 0, text.length)
|
||||||
@ -92,18 +99,28 @@ open class TextField(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun tick(tick: Long) {
|
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" + "_"
|
textElement.sText = "$textBuilder" + "_"
|
||||||
} else {
|
} else {
|
||||||
textElement.sText = textBuilder.toString()
|
textElement.sText = textBuilder.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
properties.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
override fun charInput(char: Char) {
|
override fun charInput(char: Char) {
|
||||||
if (position >= maxLength) {
|
if (position >= properties.maxLength) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
val previous = textBuilder.toString()
|
||||||
textBuilder.insert(position++, char.toString())
|
textBuilder.insert(position++, char.toString())
|
||||||
|
properties.onInput(previous, textBuilder.toString())
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val FIELD_CURSOR_BLINK_INTERVAL = 8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,28 +13,11 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.hud.elements.input
|
package de.bixilon.minosoft.gui.rendering.hud.elements.input
|
||||||
|
|
||||||
import de.bixilon.minosoft.config.key.KeyCodes
|
data class TextFieldProperties(
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
var defaultText: String = "",
|
||||||
|
var maxLength: Int = 256,
|
||||||
class SubmittableTextField(
|
var onSubmit: (text: String) -> Unit = {},
|
||||||
renderWindow: RenderWindow,
|
var onClose: () -> Unit = {},
|
||||||
defaultText: String = "",
|
var onInput: (previousText: String, nextText: String) -> Unit = { _, _ -> },
|
||||||
maxLength: Int = 256,
|
var submitCloses: Boolean = false,
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -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.RenderConstants
|
||||||
import de.bixilon.minosoft.gui.rendering.font.Font
|
import de.bixilon.minosoft.gui.rendering.font.Font
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
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.HUDElement
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.ImageNode
|
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.ImageNode
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
||||||
@ -28,14 +29,18 @@ import de.bixilon.minosoft.util.MMath
|
|||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer), ScreenResizeCallback {
|
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)
|
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() {
|
override fun init() {
|
||||||
inputField = SubmittableTextField(renderWindow = hudRenderer.renderWindow, maxLength = 256, onSubmit = {
|
inputField = TextField(
|
||||||
hudRenderer.renderWindow.connection.sender.sendChatMessage(it)
|
renderWindow = hudRenderer.renderWindow,
|
||||||
closeChat()
|
properties = TextFieldProperties(
|
||||||
})
|
maxLength = 256,
|
||||||
|
submitCloses = true,
|
||||||
|
onSubmit = { hudRenderer.renderWindow.connection.sender.sendChatMessage(it) },
|
||||||
|
onClose = { closeChat() },
|
||||||
|
))
|
||||||
|
|
||||||
layout.addChild(Vec2i(0, 0), inputField)
|
layout.addChild(Vec2i(0, 0), inputField)
|
||||||
inputField.apply()
|
inputField.apply()
|
||||||
@ -43,9 +48,6 @@ class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer), Scr
|
|||||||
hudRenderer.renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) {
|
hudRenderer.renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) {
|
||||||
openChat()
|
openChat()
|
||||||
}
|
}
|
||||||
hudRenderer.renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.CLOSE_CHAT) {
|
|
||||||
closeChat()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onScreenResize(screenDimensions: Vec2i) {
|
override fun onScreenResize(screenDimensions: Vec2i) {
|
||||||
@ -63,7 +65,6 @@ class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer), Scr
|
|||||||
|
|
||||||
fun closeChat() {
|
fun closeChat() {
|
||||||
layout.removeChild(inputFieldBackground)
|
layout.removeChild(inputFieldBackground)
|
||||||
inputField.clearText()
|
|
||||||
hudRenderer.renderWindow.inputHandler.currentKeyConsumer = null
|
hudRenderer.renderWindow.inputHandler.currentKeyConsumer = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ public class PacketSender {
|
|||||||
if (this.connection.fireEvent(event)) {
|
if (this.connection.fireEvent(event)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.log(LogMessageType.CHAT_OUT, "Sending chat message: %s", message);
|
Log.log(LogMessageType.CHAT_OUT, message);
|
||||||
this.connection.sendPacket(new ChatMessageC2SP(event.getMessage()));
|
this.connection.sendPacket(new ChatMessageC2SP(event.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user