From bfeafe86ecd49e753a179afb2b49f1b67bdec124 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Mon, 6 Sep 2021 11:20:48 +0200 Subject: [PATCH] improve font scaling, TextComponent: fix size changing bugs --- .../minosoft/gui/rendering/font/CharData.kt | 5 +- .../font/provider/BitmapFontProvider.kt | 5 ++ .../provider/LegacyUnicodeFontProvider.kt | 6 +- .../font/renderer/TextComponentRenderer.kt | 8 +-- .../gui/rendering/gui/elements/Element.kt | 4 +- .../gui/elements/text/TextElement.kt | 55 ++++++++++++++++--- .../gui/rendering/gui/hud/HUDRenderer.kt | 13 +++++ 7 files changed, 80 insertions(+), 16 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/font/CharData.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/font/CharData.kt index 020b69015..150f43546 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/font/CharData.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/font/CharData.kt @@ -32,6 +32,7 @@ class CharData( val char: Char, val texture: AbstractTexture, val width: Int, + val scaledWidth: Int, var uvStart: Vec2, var uvEnd: Vec2, ) { @@ -86,7 +87,7 @@ class CharData( val startPosition = Vec2(position) + shadowOffset - val endPosition = startPosition + Vec2(width, Font.CHAR_HEIGHT.toFloat()) + val endPosition = startPosition + Vec2(scaledWidth, Font.CHAR_HEIGHT.toFloat()) val italic = style.formatting.contains(PreChatFormattingCodes.ITALIC) @@ -110,7 +111,7 @@ class CharData( } fun calculateWidth(style: TextStyle): Int { - var width = width.toFloat() + var width = scaledWidth.toFloat() if (style.formatting.contains(PreChatFormattingCodes.SHADOWED)) { width += SHADOW_OFFSET } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/font/provider/BitmapFontProvider.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/font/provider/BitmapFontProvider.kt index 8d1e4fd98..e84481aba 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/font/provider/BitmapFontProvider.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/font/provider/BitmapFontProvider.kt @@ -17,6 +17,7 @@ import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.gui.rendering.RenderConstants import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.font.CharData +import de.bixilon.minosoft.gui.rendering.font.Font import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture import de.bixilon.minosoft.util.KUtil.asList import de.bixilon.minosoft.util.KUtil.toDouble @@ -32,6 +33,7 @@ class BitmapFontProvider( val height = data["height"]?.toInt() ?: 8 val ascent = data["ascent"].toDouble() private val chars: MutableMap = mutableMapOf() + private val heightScale = Font.CHAR_HEIGHT.toFloat() / height init { val texture = renderWindow.textureManager.staticTextures.createTexture(data["file"].toResourceLocation().texture()) @@ -85,11 +87,14 @@ class BitmapFontProvider( width = EMPTY_CHAR_WIDTH } + val scaledWidth = (width * heightScale).toInt() + val charData = CharData( renderWindow = renderWindow, char = char.toChar(), texture = texture, width = width, + scaledWidth = scaledWidth, uvStart = uvStart, uvEnd = uvEnd, ) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/font/provider/LegacyUnicodeFontProvider.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/font/provider/LegacyUnicodeFontProvider.kt index bc8c4a237..c712bf223 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/font/provider/LegacyUnicodeFontProvider.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/font/provider/LegacyUnicodeFontProvider.kt @@ -61,12 +61,15 @@ class LegacyUnicodeFontProvider( y = yEnd, ) + val width = (charXEnd - charXStart) + val scaledWidth = (width * HEIGHT_SCALE).toInt() val charData = CharData( renderWindow = renderWindow, char = char, texture = texture, - width = (charXEnd - charXStart) / (CHAR_SIZE / Font.CHAR_HEIGHT), + width = width, + scaledWidth = scaledWidth, uvStart = uvStart, uvEnd = uvEnd, ) @@ -94,6 +97,7 @@ class LegacyUnicodeFontProvider( private const val UNICODE_PAGE_SIZE = 256 private const val UNICODE_PAGES = 256 private const val CHAR_SIZE = 16 + private const val HEIGHT_SCALE = Font.CHAR_HEIGHT.toFloat() / CHAR_SIZE private val PIXEL = Vec2(1.0f) / UNICODE_PAGE_SIZE override fun build(renderWindow: RenderWindow, data: Map): LegacyUnicodeFontProvider { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/TextComponentRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/TextComponentRenderer.kt index 8622fed0c..49ddac8c1 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/TextComponentRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/TextComponentRenderer.kt @@ -33,7 +33,7 @@ object TextComponentRenderer : ChatComponentRenderer { */ fun wrap(): Boolean { val yAdd = Font.CHAR_HEIGHT + Font.VERTICAL_SPACING - if (size.y + yAdd > element.prefMaxSize.y) { + if (size.y + yAdd > element.maxSize.y) { return true } offset.x = initialOffset.x @@ -47,7 +47,7 @@ object TextComponentRenderer : ChatComponentRenderer { * @return If the text can't fit into the layout anymore */ fun add(x: Int): Boolean { - if (offset.x - initialOffset.x + x > element.prefMaxSize.x) { + if (offset.x - initialOffset.x + x > element.maxSize.x) { if (wrap()) { return true } @@ -84,13 +84,13 @@ object TextComponentRenderer : ChatComponentRenderer { if (size.y == 0) { size.y = Font.CHAR_HEIGHT + Font.VERTICAL_SPACING } - } else if (offset.x != initialOffset.x && add(Font.HORIZONTAL_SPACING)) { + } else if (offset.x != initialOffset.x && add(Font.HORIZONTAL_SPACING)) { // ToDo: Only add space when char fits return } val width = charData.calculateWidth(text) - if (offset.x == initialOffset.x && offset.x - initialOffset.x + width > element.prefMaxSize.x) { + if (offset.x == initialOffset.x && offset.x - initialOffset.x + width > element.maxSize.x) { return } consumer?.let { charData.render(offset, z, text, it) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/Element.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/Element.kt index 2ffb9ab5d..5f29d28ef 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/Element.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/Element.kt @@ -32,8 +32,8 @@ abstract class Element { val ret = Vec2i.MAX parent?.let { - ret.x = it.prefMaxSize.x - ret.y = it.prefMaxSize.y + ret.x = it.maxSize.x + ret.y = it.maxSize.y } val maxSize = Vec2i(prefMaxSize) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/text/TextElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/text/TextElement.kt index 25721dd16..a423d04b4 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/text/TextElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/text/TextElement.kt @@ -32,20 +32,57 @@ class TextElement( override var textComponent: ChatComponent = ChatComponent.of("") private set(value) { - size = minSize - if (value.message.isNotEmpty()) { - val size = Vec2i(0, 0) - ChatComponentRenderer.render(Vec2i(0, 0), Vec2i(0, 0), size, 0, this, renderWindow, null, value) - this.size = size - } field = value - parent?.childChange(this) + prepare(value) + } + + override var prefMaxSize: Vec2i + get() = super.prefMaxSize + set(value) { + super.prefMaxSize = value + checkSize() + } + + override var minSize: Vec2i + get() = super.minSize + set(value) { + super.minSize = value + checkSize() } init { textComponent = ChatComponent.of(text) } + private fun prepare(text: ChatComponent = textComponent) { + size = minSize + if (text.message.isNotEmpty()) { + val size = Vec2i(0, 0) + ChatComponentRenderer.render(Vec2i(0, 0), Vec2i(0, 0), size, 0, this, renderWindow, null, text) + this.size = size + } + parent?.childChange(this) + } + + + private fun checkSize() { + val size = Vec2i(size) + + if (size.x > maxSize.x) { + return prepare() + } + if (size.y > maxSize.y) { + return prepare() + } + + if (size.x < minSize.x) { + return prepare() + } + if (size.y < minSize.y) { + return prepare() + } + } + override fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int { ChatComponentRenderer.render(Vec2i(offset), offset, Vec2i(0, 0), z, this, renderWindow, consumer, textComponent) @@ -53,6 +90,10 @@ class TextElement( return LAYERS } + override fun toString(): String { + return textComponent.toString() + } + companion object { const val LAYERS = 4 // 1 layer for the text, 1 for strikethrough. * 2 for shadow } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/HUDRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/HUDRenderer.kt index 7992f03ae..3764a6457 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/HUDRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/hud/HUDRenderer.kt @@ -96,6 +96,17 @@ class HUDRenderer( val text3 = TextElement( + renderWindow = renderWindow, + text = TextComponent( + message = "!T→E↓S←T~_OÄBÖMÜ", + color = ChatColors.YELLOW, + formatting = mutableSetOf( + PreChatFormattingCodes.UNDERLINED, + ), + ), + ) + + val text4 = TextElement( renderWindow = renderWindow, text = TextComponent( message = "Noch viel längerer dummy normaler Text!", @@ -107,6 +118,7 @@ class HUDRenderer( ), ) text3.prefMaxSize = Vec2i(50, Int.MAX_VALUE) + text4.prefMaxSize = Vec2i(50, Int.MAX_VALUE) // ToDo: size > maxSize @@ -115,6 +127,7 @@ class HUDRenderer( layout += text1 layout += text2 layout += text3 + layout += text4 layout.render(Vec2i(0, 0), 0, mesh)