diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/font/Font.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/font/Font.kt index 5ffedc292..e9f195566 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/font/Font.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/font/Font.kt @@ -35,6 +35,8 @@ class Font( companion object { const val CHAR_HEIGHT = 8 + const val CHAR_MARGIN = 1 // used for background + const val TOTAL_CHAR_HEIGHT = CHAR_HEIGHT + 2 * CHAR_MARGIN // top and bottom const val HORIZONTAL_SPACING = 1 const val VERTICAL_SPACING = 3 } 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 9034bfd1b..dfe36b2a2 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 @@ -23,9 +23,6 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.ElementAlignments import de.bixilon.minosoft.gui.rendering.gui.elements.ElementAlignments.Companion.getOffset import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer import de.bixilon.minosoft.util.MMath.ceil -import de.bixilon.minosoft.util.logging.Log -import de.bixilon.minosoft.util.logging.LogLevels -import de.bixilon.minosoft.util.logging.LogMessageType import glm_.vec2.Vec2i object TextComponentRenderer : ChatComponentRenderer { @@ -42,7 +39,7 @@ object TextComponentRenderer : ChatComponentRenderer { fun addY(height: Int): Boolean { val nextY = offset.y + height - val nextSizeY = nextY - initialOffset.y + Font.CHAR_HEIGHT // add initial height for chars + val nextSizeY = nextY - initialOffset.y + Font.TOTAL_CHAR_HEIGHT // add initial height for chars + end margin if (nextSizeY >= elementMaxSize.y) { return true } @@ -54,18 +51,15 @@ object TextComponentRenderer : ChatComponentRenderer { } fun wrap(): Boolean { - if (addY(Font.CHAR_HEIGHT + Font.VERTICAL_SPACING)) { + if (addY(Font.TOTAL_CHAR_HEIGHT)) { return true } renderInfo.currentLine++ - offset.x = initialOffset.x + offset.x = initialOffset.x + Font.CHAR_MARGIN if (consumer == null) { // preparing phase renderInfo.lines += TextLineInfo() } else { - if (renderInfo.currentLine >= renderInfo.lines.size) { - Log.log(LogMessageType.OTHER, LogLevels.FATAL) { "Crash because of $text (size=$size, maxSize=$elementMaxSize)" } - } alignmentXOffset = fontAlignment.getOffset(element.size.x, renderInfo.lines[renderInfo.currentLine].width) } return false @@ -73,7 +67,7 @@ object TextComponentRenderer : ChatComponentRenderer { fun addX(width: Int, wrap: Boolean = true): Boolean { val nextX = offset.x + width - val nextSizeX = nextX + alignmentXOffset - initialOffset.x + val nextSizeX = nextX - initialOffset.x + Font.CHAR_MARGIN // end margin if (nextSizeX > elementMaxSize.x) { if (!wrap) { return true @@ -96,7 +90,7 @@ object TextComponentRenderer : ChatComponentRenderer { if (size.y == 0) { // Add initial height of the letter for the first line - val nextSizeY = Font.CHAR_HEIGHT + val nextSizeY = Font.TOTAL_CHAR_HEIGHT if (nextSizeY > elementMaxSize.y) { return true } @@ -106,6 +100,8 @@ object TextComponentRenderer : ChatComponentRenderer { renderInfo.lines += TextLineInfo() // add line 0 } size.y = nextSizeY + size.x += Font.CHAR_MARGIN * 2 + offset += Font.CHAR_MARGIN } @@ -119,7 +115,7 @@ object TextComponentRenderer : ChatComponentRenderer { } // skip spaces that are wrapped (because of a line break) - if (offset.y != initialOffset.y && offset.x == initialOffset.x && char == ' ') { + if (offset.y != initialOffset.y + Font.CHAR_MARGIN && offset.x == initialOffset.x + Font.CHAR_MARGIN && char == ' ') { continue } @@ -128,7 +124,7 @@ object TextComponentRenderer : ChatComponentRenderer { val charWidth = charData.calculateWidth(text) var width = charWidth - if (offset.x != initialOffset.x) { + if (offset.x != initialOffset.x + Font.CHAR_MARGIN) { // add spacing between letters width += Font.HORIZONTAL_SPACING } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/spacer/LineSpacerElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/spacer/LineSpacerElement.kt index d8e286e53..dfd0c7d88 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/spacer/LineSpacerElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/elements/spacer/LineSpacerElement.kt @@ -24,7 +24,7 @@ class LineSpacerElement( ) : SpacerElement(hudRenderer, Vec2i.EMPTY) { override var size: Vec2i - get() = Vec2i(0, (lines * Font.CHAR_HEIGHT) + ((lines + 1) * Font.VERTICAL_SPACING)) + get() = Vec2i(0, lines * Font.TOTAL_CHAR_HEIGHT) set(value) { TODO("Can not set the size of an FontSpacer! Use a normal spacer instead!") } 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 dd302df66..38b05ed1d 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 @@ -14,10 +14,14 @@ package de.bixilon.minosoft.gui.rendering.gui.elements.text import de.bixilon.minosoft.data.text.ChatComponent +import de.bixilon.minosoft.data.text.RGBColor +import de.bixilon.minosoft.gui.rendering.RenderConstants +import de.bixilon.minosoft.gui.rendering.font.Font import de.bixilon.minosoft.gui.rendering.font.renderer.ChatComponentRenderer import de.bixilon.minosoft.gui.rendering.font.renderer.TextRenderInfo import de.bixilon.minosoft.gui.rendering.gui.elements.Element import de.bixilon.minosoft.gui.rendering.gui.elements.ElementAlignments +import de.bixilon.minosoft.gui.rendering.gui.elements.ElementAlignments.Companion.getOffset import de.bixilon.minosoft.gui.rendering.gui.elements.InfiniteSizeElement import de.bixilon.minosoft.gui.rendering.gui.hud.HUDRenderer import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer @@ -29,6 +33,8 @@ open class TextElement( hudRenderer: HUDRenderer, text: Any, override var fontAlignment: ElementAlignments = ElementAlignments.LEFT, + var background: Boolean = true, + var backgroundColor: RGBColor = RenderConstants.TEXT_BACKGROUND_COLOR, ) : LabeledElement(hudRenderer) { private var preparedSize = Vec2i.EMPTY private var renderInfo = TextRenderInfo() @@ -91,9 +97,18 @@ open class TextElement( override fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int { val initialOffset = offset + margin.offset - ChatComponentRenderer.render(initialOffset, Vec2i(initialOffset), Vec2i.EMPTY, z, this, fontAlignment, renderWindow, consumer, renderInfo, textComponent) + + ChatComponentRenderer.render(initialOffset, Vec2i(initialOffset), Vec2i.EMPTY, z + 1, this, fontAlignment, renderWindow, consumer, renderInfo, textComponent) renderInfo.currentLine = 0 prepared = true + + if (background) { + for ((line, info) in renderInfo.lines.withIndex()) { + val start = initialOffset + Vec2i(fontAlignment.getOffset(size.x, info.width), line * Font.TOTAL_CHAR_HEIGHT) + consumer.addQuad(start, start + Vec2i(info.width + Font.CHAR_MARGIN, Font.TOTAL_CHAR_HEIGHT), z, renderWindow.WHITE_TEXTURE, backgroundColor) + } + } + return LAYERS } @@ -102,6 +117,6 @@ open class TextElement( } companion object { - const val LAYERS = 4 // 1 layer for the text, 1 for strikethrough. * 2 for shadow + const val LAYERS = 5 // 1 layer for the text, 1 for strikethrough, * 2 for shadow, 1 for background } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/mesh/GUIVertexConsumer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/mesh/GUIVertexConsumer.kt index be92a334d..141fd6d90 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/mesh/GUIVertexConsumer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/mesh/GUIVertexConsumer.kt @@ -14,11 +14,36 @@ package de.bixilon.minosoft.gui.rendering.gui.mesh import de.bixilon.minosoft.data.text.RGBColor +import de.bixilon.minosoft.gui.rendering.gui.hud.atlas.TextureLike import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture +import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh import glm_.vec2.Vec2 import glm_.vec2.Vec2t interface GUIVertexConsumer { fun addVertex(position: Vec2t<*>, z: Int, texture: AbstractTexture, uv: Vec2, tint: RGBColor) + + fun addQuad(start: Vec2t<*>, end: Vec2t<*>, z: Int, texture: AbstractTexture, uvStart: Vec2, uvEnd: Vec2, tint: RGBColor) { + val positions = arrayOf( + Vec2(start.x.toFloat(), start.y), + Vec2(end.x.toFloat(), start.y), + end, + Vec2(start.x, end.y), + ) + val texturePositions = arrayOf( + Vec2(uvEnd.x, uvStart.y), + uvStart, + Vec2(uvStart.x, uvEnd.y), + uvEnd, + ) + + for ((vertexIndex, textureIndex) in Mesh.QUAD_DRAW_ODER) { + addVertex(positions[vertexIndex], z, texture, texturePositions[textureIndex], tint) + } + } + + fun addQuad(start: Vec2t<*>, end: Vec2t<*>, z: Int, texture: TextureLike, tint: RGBColor) { + addQuad(start, end, z, texture.texture, texture.uvStart, texture.uvEnd, tint) + } }