improve TextComponent, LabelNode rendering

This commit is contained in:
Bixilon 2021-04-30 00:25:49 +02:00
parent f8cd02aca0
commit efe05ed03f
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
9 changed files with 43 additions and 30 deletions

View File

@ -23,6 +23,5 @@ enum class Hands {
companion object : ValuesEnum<Hands> { companion object : ValuesEnum<Hands> {
override val VALUES: Array<Hands> = values() override val VALUES: Array<Hands> = values()
override val NAME_MAP: Map<String, Hands> = KUtil.getEnumValues(VALUES) override val NAME_MAP: Map<String, Hands> = KUtil.getEnumValues(VALUES)
} }
} }

View File

@ -193,7 +193,6 @@ class BaseComponent : ChatComponent {
return legacyText return legacyText
} }
private fun <T> MutableSet<T>.addOrRemove(value: T, addOrRemove: Boolean?) { private fun <T> MutableSet<T>.addOrRemove(value: T, addOrRemove: Boolean?) {
if (addOrRemove == null) { if (addOrRemove == null) {
return return

View File

@ -170,33 +170,43 @@ open class TextComponent(
// bring chars in right order and reverse them if right bound // bring chars in right order and reverse them if right bound
val charArray = this.message.toCharArray().toList() val charArray = this.message.toCharArray().toList()
fun checkGetSize(charEnd: Vec2i) {
if (charEnd.x > getProperties.size.x) {
getProperties.size.x = charEnd.x
}
if (charEnd.y > getProperties.size.y) {
getProperties.size.y = charEnd.y
}
}
fun pushNewLine() {
offset.x = 0
offset.y += Font.CHAR_HEIGHT + RenderConstants.TEXT_LINE_PADDING
checkGetSize(Vec2i(0, 0))
}
// add all chars // add all chars
for (char in charArray) { for (char in charArray) {
if (char == '\n') { if (ProtocolDefinition.LINE_BREAK_CHARS.contains(char)) {
offset.x = 0 pushNewLine()
val yOffset = Font.CHAR_HEIGHT + RenderConstants.TEXT_LINE_PADDING
offset.y += yOffset
getProperties.size.y += yOffset
continue continue
} }
val fontChar = renderWindow.font.getChar(char) val fontChar = renderWindow.font.getChar(char)
val scaledWidth = (fontChar.size.x * (Font.CHAR_HEIGHT / fontChar.height.toFloat())).toInt() val charSize = fontChar.size
val charStart = startPosition + offset var charStart = Vec2i(offset)
textElement.addChild(charStart, ImageNode(renderWindow, NodeSizing(minSize = Vec2i(scaledWidth, Font.CHAR_HEIGHT)), fontChar, 1, color)) var charEnd = charStart + charSize
// ad spacer between chars if (charEnd.x >= setProperties.hardWrap) {
offset.x += scaledWidth + Font.SPACE_BETWEEN_CHARS pushNewLine()
if (offset.x > getProperties.size.x) { charStart = Vec2i(offset)
getProperties.size.x += scaledWidth + Font.SPACE_BETWEEN_CHARS charEnd = charStart + charSize
}
if (offset.y >= getProperties.size.y) {
if (getProperties.size.y < fontChar.height) {
getProperties.size.y = fontChar.height
}
getProperties.lines = (offset.y + Font.CHAR_HEIGHT) / (Font.CHAR_HEIGHT + RenderConstants.TEXT_LINE_PADDING)
} }
textElement.addChild(charStart + startPosition, ImageNode(renderWindow, NodeSizing(minSize = charSize), fontChar, 1, color))
offset.x += charSize.x + Font.SPACE_BETWEEN_CHARS
checkGetSize(charEnd)
} }
} }
} }

View File

@ -45,7 +45,7 @@ object RenderConstants {
val TEXT_BACKGROUND_COLOR = RGBColor(0, 0, 0, 80) val TEXT_BACKGROUND_COLOR = RGBColor(0, 0, 0, 80)
const val TEXT_LINE_PADDING = 0 const val TEXT_LINE_PADDING = 2
val WORD_SEPARATORS = arrayOf(' ', '.', ',', '!', '-', '?') val WORD_SEPARATORS = arrayOf(' ', '.', ',', '!', '-', '?')
const val CHUNK_SECTIONS_PER_MESH = 1 const val CHUNK_SECTIONS_PER_MESH = 1

View File

@ -25,7 +25,7 @@ data class FontChar(
val column: Int, val column: Int,
var startPixel: Int, var startPixel: Int,
var endPixel: Int, var endPixel: Int,
val height: Int, private val height: Int,
) : TextureLike { ) : TextureLike {
override lateinit var uvStart: Vec2 override lateinit var uvStart: Vec2
private set private set

View File

@ -14,7 +14,6 @@
package de.bixilon.minosoft.gui.rendering.hud.nodes.debug package de.bixilon.minosoft.gui.rendering.hud.nodes.debug
import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
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.LabelNode import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
@ -25,7 +24,7 @@ abstract class DebugScreenNode(hudRenderer: HUDRenderer) : HUDElement(hudRendere
fun text(text: String = ""): LabelNode { fun text(text: String = ""): LabelNode {
val textElement = LabelNode(hudRenderer.renderWindow, text = ChatComponent.of(text)) val textElement = LabelNode(hudRenderer.renderWindow, text = ChatComponent.of(text))
layout.addChild(Vec2i(0, layout.sizing.currentSize.y + RenderConstants.TEXT_LINE_PADDING), textElement) layout.addChild(Vec2i(0, layout.sizing.currentSize.y), textElement)
layout.apply() layout.apply()
return textElement return textElement
} }

View File

@ -26,7 +26,7 @@ import glm_.vec2.Vec2i
class LabelNode( class LabelNode(
renderWindow: RenderWindow, renderWindow: RenderWindow,
sizing: NodeSizing = NodeSizing(minSize = Vec2i(0, Font.CHAR_HEIGHT)), sizing: NodeSizing = NodeSizing(minSize = Vec2i(0, Font.CHAR_HEIGHT + 2 * TEXT_BACKGROUND_OFFSET)),
text: ChatComponent = ChatComponent.of(""), text: ChatComponent = ChatComponent.of(""),
var background: Boolean = true, var background: Boolean = true,
val setProperties: TextSetProperties = TextSetProperties(), val setProperties: TextSetProperties = TextSetProperties(),
@ -54,15 +54,20 @@ class LabelNode(
private fun prepare() { private fun prepare() {
clearChildren() clearChildren()
getProperties = TextGetProperties() getProperties = TextGetProperties()
text.prepareRender(Vec2i(1, 1), Vec2i(), renderWindow, this, 1, setProperties, getProperties) val textStartPosition = Vec2i(TEXT_BACKGROUND_OFFSET, TEXT_BACKGROUND_OFFSET)
apply() text.prepareRender(textStartPosition, Vec2i(), renderWindow, this, 1, setProperties, getProperties)
if (background) { if (background && text.message.isNotBlank()) {
drawBackground(getProperties.size + 1) drawBackground(getProperties.size + textStartPosition + TEXT_BACKGROUND_OFFSET)
} }
apply()
} }
private fun drawBackground(end: Vec2i, z: Int = 1, tintColor: RGBColor = RenderConstants.TEXT_BACKGROUND_COLOR) { private fun drawBackground(end: Vec2i, z: Int = 1, tintColor: RGBColor = RenderConstants.TEXT_BACKGROUND_COLOR) {
addChild(Vec2i(0, 0), ImageNode(renderWindow, NodeSizing(minSize = end), renderWindow.WHITE_TEXTURE, 0, tintColor)) addChild(Vec2i(0, 0), ImageNode(renderWindow, NodeSizing(minSize = end), renderWindow.WHITE_TEXTURE, 0, tintColor))
} }
companion object {
private const val TEXT_BACKGROUND_OFFSET = 1
}
} }

View File

@ -106,6 +106,8 @@ public final class ProtocolDefinition {
public static final RGBColor DEFAULT_COLOR = ChatColors.WHITE; public static final RGBColor DEFAULT_COLOR = ChatColors.WHITE;
public static final char[] LINE_BREAK_CHARS = {'\n', '\r'};
public static final String[] RELEVANT_MINECRAFT_ASSETS = {"minecraft/lang/", "minecraft/sounds.json", "minecraft/sounds/", "minecraft/textures/", "minecraft/font/"}; // whitelist for all assets we care (we have our own block models, etc) public static final String[] RELEVANT_MINECRAFT_ASSETS = {"minecraft/lang/", "minecraft/sounds.json", "minecraft/sounds/", "minecraft/textures/", "minecraft/font/"}; // whitelist for all assets we care (we have our own block models, etc)

View File

@ -63,5 +63,4 @@ void main() {
passSecondTextureCoordinates = vec3(textureIndex, secondTexture & 0xFFFFFFu); passSecondTextureCoordinates = vec3(textureIndex, secondTexture & 0xFFFFFFu);
passInterpolateBetweenTextures = interpolation / 100.0f; passInterpolateBetweenTextures = interpolation / 100.0f;
} }