wip: hud: re-add chat input field

This commit is contained in:
Bixilon 2021-04-14 20:24:56 +02:00
parent e511647460
commit 48fdbd457a
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
9 changed files with 241 additions and 11 deletions

View File

@ -53,8 +53,8 @@ abstract class Entity(
Vec3(+(entityType.width / 2 + HITBOX_MARGIN), entityType.height, +(entityType.width / 2 + HITBOX_MARGIN))
)
fun forceMove(relativePosition: Vec3) {
position = position + relativePosition
fun forceMove(deltaPosition: Vec3) {
position = position + deltaPosition
}
fun addEffect(effect: StatusEffectInstance) {
@ -202,6 +202,7 @@ abstract class Entity(
val blockPositions = (originalAABB extend deltaPosition extend Directions.DOWN.directionVector).getBlockPositions()
val result = VoxelShape()
for (blockPosition in blockPositions) {
// ToDo: Check if chunk is loaded
val blockState = connection.world.getBlockState(blockPosition) ?: continue
result.add(blockState.collisionShape + blockPosition)
}

View File

@ -23,11 +23,13 @@ import de.bixilon.minosoft.gui.rendering.Renderer
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
import de.bixilon.minosoft.gui.rendering.hud.elements.other.CrosshairHUDElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.chat.ChatBoxHUDElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.debug.HUDSystemDebugNode
import de.bixilon.minosoft.gui.rendering.hud.nodes.debug.HUDWorldDebugNode
import de.bixilon.minosoft.gui.rendering.shader.Shader
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.MMath
import de.bixilon.minosoft.util.json.ResourceLocationJsonMap.toResourceLocationMap
import glm_.glm
import glm_.mat4x4.Mat4
@ -87,6 +89,11 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
toggleKeyBinding = KeyBindingsNames.TOGGLE_DEBUG_SCREEN,
enabled = false,
))
addElement(ElementsNames.CHAT_RESOURCE_LOCATION, ChatBoxHUDElement(this), HUDElementProperties(
position = Vec2(0.0f, -1.0f),
xBinding = HUDElementProperties.PositionBindings.CENTER,
))
}
fun addElement(resourceLocation: ResourceLocation, hudElement: HUDElement, defaultProperties: HUDElementProperties) {
@ -174,6 +181,8 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
for ((elementProperties, hudElement) in enabledHUDElement.values) {
val realScaleFactor = elementProperties.scale * Minosoft.getConfig().config.game.hud.scale
val realSize = hudElement.layout.sizing.currentSize * realScaleFactor
realSize.x = MMath.clamp(realSize.x, hudElement.layout.sizing.minSize.x, hudElement.layout.sizing.maxSize.x)
realSize.y = MMath.clamp(realSize.y, hudElement.layout.sizing.minSize.y, hudElement.layout.sizing.maxSize.y)
val elementStart = getRealPosition(realSize, elementProperties, renderWindow.screenDimensions)

View File

@ -0,0 +1,40 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
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)
}
}

View File

@ -0,0 +1,104 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.hud.elements.input
import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.ImageNode
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
import de.bixilon.minosoft.util.MMath
import glm_.vec2.Vec2i
open class TextField(
renderWindow: RenderWindow,
defaultText: String = "",
var maxLength: Int = 256,
) : AbsoluteLayout(renderWindow), KeyConsumer, MouseConsumer {
override var focused: Boolean = true
private var textBuilder: StringBuilder = StringBuilder(defaultText)
private val textElement = LabelNode(renderWindow, sizing = sizing, text = ChatComponent.valueOf(raw = text), background = false)
private var position = text.length
var text: String
get() = textBuilder.toString()
set(value) {
position = value.length
textBuilder = StringBuilder(value)
update()
}
init {
addChild(Vec2i(0, 0), textElement)
addChild(Vec2i(0, 0), ImageNode(renderWindow, sizing = sizing, renderWindow.WHITE_TEXTURE, 0, RenderConstants.TEXT_BACKGROUND_COLOR))
clearChildrenCache()
}
fun clearText() {
textBuilder.clear()
update()
}
private fun update() {
textElement.text = ChatComponent.valueOf(raw = text)
}
override fun keyInput(keyCodes: KeyCodes) {
when (keyCodes) {
KeyCodes.KEY_BACKSPACE -> {
if (textBuilder.isEmpty()) {
return
}
textBuilder.deleteCharAt(--position)
}
KeyCodes.KEY_DELETE -> {
if (textBuilder.isEmpty() || position == textBuilder.length) {
return
}
textBuilder.deleteCharAt(position)
}
KeyCodes.KEY_ENTER -> {
if (position > maxLength) {
return
}
textBuilder.insert(position++, '\n')
}
KeyCodes.KEY_LEFT -> {
position = MMath.clamp(position - 1, 0, text.length)
return
}
KeyCodes.KEY_RIGHT -> {
position = MMath.clamp(position + 1, 0, text.length)
return
}
// ToDo: Up and down for line breaks, shift and ctrl modifier, ...
else -> {
return
}
}
update()
super.keyInput(keyCodes)
}
override fun charInput(char: Char) {
if (position >= maxLength) {
return
}
textBuilder.insert(position++, char.toString())
update()
}
}

View File

@ -0,0 +1,62 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.hud.nodes.chat
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
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.nodes.HUDElement
import glm_.vec2.Vec2i
class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer) {
private lateinit var inputField: SubmittableTextField
override fun init() {
inputField = SubmittableTextField(renderWindow = hudRenderer.renderWindow, maxLength = 256, onSubmit = {
hudRenderer.renderWindow.connection.sender.sendChatMessage(it)
closeChat()
})
layout.addChild(Vec2i(0, 0), inputField)
inputField.apply()
hudRenderer.renderWindow.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) { _, _ ->
openChat()
}
hudRenderer.renderWindow.registerKeyCallback(KeyBindingsNames.CLOSE_CHAT) { _, _ ->
closeChat()
}
}
override fun screenChangeResizeCallback(screenDimensions: Vec2i) {
layout.sizing.minSize.x = screenDimensions.x
layout.sizing.maxSize.x = screenDimensions.x
layout.sizing.validate()
layout.apply()
}
fun openChat() {
hudRenderer.renderWindow.currentKeyConsumer = inputField
hudRenderer.renderWindow.currentElement.remove(KeyBindingsNames.WHEN_IN_GAME)
hudRenderer.renderWindow.currentElement.add(KeyBindingsNames.WHEN_IN_CHAT)
}
fun closeChat() {
inputField.clearText()
hudRenderer.renderWindow.currentKeyConsumer = null
hudRenderer.renderWindow.currentElement.remove(KeyBindingsNames.WHEN_IN_CHAT)
hudRenderer.renderWindow.currentElement.add(KeyBindingsNames.WHEN_IN_GAME)
}
}

View File

@ -83,8 +83,7 @@ open class AbsoluteLayout(
private fun recalculateSize() {
if (children.isEmpty()) {
sizing.currentSize.x = sizing.minSize.x
sizing.currentSize.y = sizing.minSize.y
sizing.currentSize = Vec2i(sizing.minSize)
} else {
for ((childNode, start) in children) {
checkSize(childNode, start)

View File

@ -37,6 +37,7 @@ class LabelNode(
prepare()
apply()
}
var sText: String
get() = text.message
set(value) {

View File

@ -13,14 +13,20 @@
package de.bixilon.minosoft.gui.rendering.hud.nodes.properties
import de.bixilon.minosoft.util.MMath
import glm_.vec2.Vec2i
data class NodeSizing(
val minSize: Vec2i = Vec2i(0, 0),
val margin: Spacing = Spacing(),
val padding: Spacing = Spacing(),
val maxSize: Vec2i = Vec2i(Int.MAX_VALUE, Int.MAX_VALUE),
var minSize: Vec2i = Vec2i(0, 0),
var margin: Spacing = Spacing(0, 0, 0, 0),
var padding: Spacing = Spacing(0, 0, 0, 0),
var maxSize: Vec2i = Vec2i(Int.MAX_VALUE, Int.MAX_VALUE),
var forceAlign: NodeAlignment? = null,
) {
val currentSize: Vec2i = Vec2i(minSize)
var currentSize: Vec2i = Vec2i(minSize)
fun validate() {
MMath.clamp(currentSize, minSize, maxSize)
}
}

View File

@ -13,6 +13,8 @@
package de.bixilon.minosoft.util
import glm_.vec2.Vec2i
object MMath {
fun minClamp(value: Int, min: Int): Int {
@ -22,6 +24,12 @@ object MMath {
return value
}
fun clamp(value: Vec2i, min: Vec2i, max: Vec2i): Vec2i {
value.x = clamp(value.x, min.x, max.x)
value.y = clamp(value.y, min.y, max.y)
return value
}
fun clamp(value: Int, min: Int, max: Int): Int {
if (value < min) {
return min