mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 03:44:54 -04:00
improve font scaling, TextComponent: fix size changing bugs
This commit is contained in:
parent
e736e58001
commit
bfeafe86ec
@ -32,6 +32,7 @@ class CharData(
|
|||||||
val char: Char,
|
val char: Char,
|
||||||
val texture: AbstractTexture,
|
val texture: AbstractTexture,
|
||||||
val width: Int,
|
val width: Int,
|
||||||
|
val scaledWidth: Int,
|
||||||
var uvStart: Vec2,
|
var uvStart: Vec2,
|
||||||
var uvEnd: Vec2,
|
var uvEnd: Vec2,
|
||||||
) {
|
) {
|
||||||
@ -86,7 +87,7 @@ class CharData(
|
|||||||
|
|
||||||
|
|
||||||
val startPosition = Vec2(position) + shadowOffset
|
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)
|
val italic = style.formatting.contains(PreChatFormattingCodes.ITALIC)
|
||||||
@ -110,7 +111,7 @@ class CharData(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun calculateWidth(style: TextStyle): Int {
|
fun calculateWidth(style: TextStyle): Int {
|
||||||
var width = width.toFloat()
|
var width = scaledWidth.toFloat()
|
||||||
if (style.formatting.contains(PreChatFormattingCodes.SHADOWED)) {
|
if (style.formatting.contains(PreChatFormattingCodes.SHADOWED)) {
|
||||||
width += SHADOW_OFFSET
|
width += SHADOW_OFFSET
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import de.bixilon.minosoft.data.registries.ResourceLocation
|
|||||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||||
import de.bixilon.minosoft.gui.rendering.font.CharData
|
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.gui.rendering.textures.TextureUtil.texture
|
||||||
import de.bixilon.minosoft.util.KUtil.asList
|
import de.bixilon.minosoft.util.KUtil.asList
|
||||||
import de.bixilon.minosoft.util.KUtil.toDouble
|
import de.bixilon.minosoft.util.KUtil.toDouble
|
||||||
@ -32,6 +33,7 @@ class BitmapFontProvider(
|
|||||||
val height = data["height"]?.toInt() ?: 8
|
val height = data["height"]?.toInt() ?: 8
|
||||||
val ascent = data["ascent"].toDouble()
|
val ascent = data["ascent"].toDouble()
|
||||||
private val chars: MutableMap<Char, CharData> = mutableMapOf()
|
private val chars: MutableMap<Char, CharData> = mutableMapOf()
|
||||||
|
private val heightScale = Font.CHAR_HEIGHT.toFloat() / height
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val texture = renderWindow.textureManager.staticTextures.createTexture(data["file"].toResourceLocation().texture())
|
val texture = renderWindow.textureManager.staticTextures.createTexture(data["file"].toResourceLocation().texture())
|
||||||
@ -85,11 +87,14 @@ class BitmapFontProvider(
|
|||||||
width = EMPTY_CHAR_WIDTH
|
width = EMPTY_CHAR_WIDTH
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val scaledWidth = (width * heightScale).toInt()
|
||||||
|
|
||||||
val charData = CharData(
|
val charData = CharData(
|
||||||
renderWindow = renderWindow,
|
renderWindow = renderWindow,
|
||||||
char = char.toChar(),
|
char = char.toChar(),
|
||||||
texture = texture,
|
texture = texture,
|
||||||
width = width,
|
width = width,
|
||||||
|
scaledWidth = scaledWidth,
|
||||||
uvStart = uvStart,
|
uvStart = uvStart,
|
||||||
uvEnd = uvEnd,
|
uvEnd = uvEnd,
|
||||||
)
|
)
|
||||||
|
@ -61,12 +61,15 @@ class LegacyUnicodeFontProvider(
|
|||||||
y = yEnd,
|
y = yEnd,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val width = (charXEnd - charXStart)
|
||||||
|
val scaledWidth = (width * HEIGHT_SCALE).toInt()
|
||||||
|
|
||||||
val charData = CharData(
|
val charData = CharData(
|
||||||
renderWindow = renderWindow,
|
renderWindow = renderWindow,
|
||||||
char = char,
|
char = char,
|
||||||
texture = texture,
|
texture = texture,
|
||||||
width = (charXEnd - charXStart) / (CHAR_SIZE / Font.CHAR_HEIGHT),
|
width = width,
|
||||||
|
scaledWidth = scaledWidth,
|
||||||
uvStart = uvStart,
|
uvStart = uvStart,
|
||||||
uvEnd = uvEnd,
|
uvEnd = uvEnd,
|
||||||
)
|
)
|
||||||
@ -94,6 +97,7 @@ class LegacyUnicodeFontProvider(
|
|||||||
private const val UNICODE_PAGE_SIZE = 256
|
private const val UNICODE_PAGE_SIZE = 256
|
||||||
private const val UNICODE_PAGES = 256
|
private const val UNICODE_PAGES = 256
|
||||||
private const val CHAR_SIZE = 16
|
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
|
private val PIXEL = Vec2(1.0f) / UNICODE_PAGE_SIZE
|
||||||
|
|
||||||
override fun build(renderWindow: RenderWindow, data: Map<String, Any>): LegacyUnicodeFontProvider {
|
override fun build(renderWindow: RenderWindow, data: Map<String, Any>): LegacyUnicodeFontProvider {
|
||||||
|
@ -33,7 +33,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
*/
|
*/
|
||||||
fun wrap(): Boolean {
|
fun wrap(): Boolean {
|
||||||
val yAdd = Font.CHAR_HEIGHT + Font.VERTICAL_SPACING
|
val yAdd = Font.CHAR_HEIGHT + Font.VERTICAL_SPACING
|
||||||
if (size.y + yAdd > element.prefMaxSize.y) {
|
if (size.y + yAdd > element.maxSize.y) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
offset.x = initialOffset.x
|
offset.x = initialOffset.x
|
||||||
@ -47,7 +47,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
* @return If the text can't fit into the layout anymore
|
* @return If the text can't fit into the layout anymore
|
||||||
*/
|
*/
|
||||||
fun add(x: Int): Boolean {
|
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()) {
|
if (wrap()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -84,13 +84,13 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
if (size.y == 0) {
|
if (size.y == 0) {
|
||||||
size.y = Font.CHAR_HEIGHT + Font.VERTICAL_SPACING
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val width = charData.calculateWidth(text)
|
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
|
return
|
||||||
}
|
}
|
||||||
consumer?.let { charData.render(offset, z, text, it) }
|
consumer?.let { charData.render(offset, z, text, it) }
|
||||||
|
@ -32,8 +32,8 @@ abstract class Element {
|
|||||||
val ret = Vec2i.MAX
|
val ret = Vec2i.MAX
|
||||||
|
|
||||||
parent?.let {
|
parent?.let {
|
||||||
ret.x = it.prefMaxSize.x
|
ret.x = it.maxSize.x
|
||||||
ret.y = it.prefMaxSize.y
|
ret.y = it.maxSize.y
|
||||||
}
|
}
|
||||||
|
|
||||||
val maxSize = Vec2i(prefMaxSize)
|
val maxSize = Vec2i(prefMaxSize)
|
||||||
|
@ -32,20 +32,57 @@ class TextElement(
|
|||||||
|
|
||||||
override var textComponent: ChatComponent = ChatComponent.of("")
|
override var textComponent: ChatComponent = ChatComponent.of("")
|
||||||
private set(value) {
|
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
|
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 {
|
init {
|
||||||
textComponent = ChatComponent.of(text)
|
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 {
|
override fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int {
|
||||||
ChatComponentRenderer.render(Vec2i(offset), offset, Vec2i(0, 0), z, this, renderWindow, consumer, textComponent)
|
ChatComponentRenderer.render(Vec2i(offset), offset, Vec2i(0, 0), z, this, renderWindow, consumer, textComponent)
|
||||||
@ -53,6 +90,10 @@ class TextElement(
|
|||||||
return LAYERS
|
return LAYERS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return textComponent.toString()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val LAYERS = 4 // 1 layer for the text, 1 for strikethrough. * 2 for shadow
|
const val LAYERS = 4 // 1 layer for the text, 1 for strikethrough. * 2 for shadow
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,17 @@ class HUDRenderer(
|
|||||||
|
|
||||||
|
|
||||||
val text3 = TextElement(
|
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,
|
renderWindow = renderWindow,
|
||||||
text = TextComponent(
|
text = TextComponent(
|
||||||
message = "Noch viel längerer dummy normaler Text!",
|
message = "Noch viel längerer dummy normaler Text!",
|
||||||
@ -107,6 +118,7 @@ class HUDRenderer(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
text3.prefMaxSize = Vec2i(50, Int.MAX_VALUE)
|
text3.prefMaxSize = Vec2i(50, Int.MAX_VALUE)
|
||||||
|
text4.prefMaxSize = Vec2i(50, Int.MAX_VALUE)
|
||||||
|
|
||||||
// ToDo: size > maxSize
|
// ToDo: size > maxSize
|
||||||
|
|
||||||
@ -115,6 +127,7 @@ class HUDRenderer(
|
|||||||
layout += text1
|
layout += text1
|
||||||
layout += text2
|
layout += text2
|
||||||
layout += text3
|
layout += text3
|
||||||
|
layout += text4
|
||||||
|
|
||||||
|
|
||||||
layout.render(Vec2i(0, 0), 0, mesh)
|
layout.render(Vec2i(0, 0), 0, mesh)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user