mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-15 18:34:56 -04:00
font rendering improvements, rasterized font renderer test
This commit is contained in:
parent
63b8c73150
commit
a870d64d6f
@ -222,7 +222,7 @@ testing {
|
|||||||
options {
|
options {
|
||||||
val options = this as TestNGOptions
|
val options = this as TestNGOptions
|
||||||
options.preserveOrder = true
|
options.preserveOrder = true
|
||||||
// options.excludeGroups("pixlyzer", "light", "packet", "version", "container", "item_stack", "signature", "private_key", "interaction", "item_digging", "world_renderer", "rendering")
|
options.excludeGroups("command", "registry", "biome", "input", "version", "fluid", "world", "raycasting", "pixlyzer", "item", "block", "physics", "light", "packet", "container", "item_stack", "signature", "private_key", "interaction", "item_digging", "world_renderer", "rendering")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2023 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.font.renderer.code
|
||||||
|
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
|
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.dummy.texture.DummyTexture
|
||||||
|
|
||||||
|
class DummyCodePointRenderer(
|
||||||
|
override val uvStart: Vec2 = Vec2(0.1f, 0.2f),
|
||||||
|
override val uvEnd: Vec2 = Vec2(0.6f, 0.7f),
|
||||||
|
override val width: Float = 5.0f,
|
||||||
|
) : RasterizedCodePointRenderer {
|
||||||
|
override val texture = DummyTexture(minosoft("test"))
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2023 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.font.renderer.code
|
||||||
|
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
|
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
||||||
|
import de.bixilon.minosoft.data.text.formatting.color.ChatColors
|
||||||
|
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.DummyGUIVertexConsumer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||||
|
import org.testng.Assert.assertEquals
|
||||||
|
import org.testng.Assert.assertNull
|
||||||
|
import org.testng.annotations.Test
|
||||||
|
|
||||||
|
@Test(groups = ["font"], priority = -1)
|
||||||
|
class RasterizedCodePointRendererTest {
|
||||||
|
|
||||||
|
fun verifySimpleSetup() {
|
||||||
|
val consumer = object : DummyGUIVertexConsumer() {
|
||||||
|
override fun addChar(start: Vec2, end: Vec2, texture: AbstractTexture, uvStart: Vec2, uvEnd: Vec2, italic: Boolean, tint: RGBColor, options: GUIVertexOptions?) {
|
||||||
|
this.char++
|
||||||
|
assertEquals(tint, ChatColors.BLUE)
|
||||||
|
assertEquals(uvStart, Vec2(0.1, 0.2))
|
||||||
|
assertEquals(uvEnd, Vec2(0.6, 0.7))
|
||||||
|
assertEquals(texture.resourceLocation, minosoft("test"))
|
||||||
|
assertNull(options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val char = DummyCodePointRenderer()
|
||||||
|
|
||||||
|
char.render(Vec2(10.0f, 12.0f), ChatColors.BLUE, false, false, false, 1.0f, consumer, null)
|
||||||
|
|
||||||
|
assertEquals(1, consumer.char)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun verifyComplexSetup() {
|
||||||
|
var chars = 0
|
||||||
|
val consumer = object : DummyGUIVertexConsumer() {
|
||||||
|
override fun addChar(start: Vec2, end: Vec2, texture: AbstractTexture, uvStart: Vec2, uvEnd: Vec2, italic: Boolean, tint: RGBColor, options: GUIVertexOptions?) {
|
||||||
|
chars++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val char = DummyCodePointRenderer()
|
||||||
|
|
||||||
|
char.render(Vec2(10.0f, 12.0f), ChatColors.BLUE, true, true, false, 1.0f, consumer, null)
|
||||||
|
|
||||||
|
assertEquals(4, chars)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unformatted() {
|
||||||
|
val consumer = object : DummyGUIVertexConsumer() {
|
||||||
|
override fun addChar(start: Vec2, end: Vec2, index: Int) {
|
||||||
|
assertEquals(start, Vec2(10.0f, 13.0f)) // top spacing
|
||||||
|
assertEquals(end, Vec2(15.0f, 21.0f)) // start + width | start + height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val char = DummyCodePointRenderer()
|
||||||
|
|
||||||
|
char.render(Vec2(10.0f, 12.0f), ChatColors.BLUE, false, false, false, 1.0f, consumer, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scaled() {
|
||||||
|
val consumer = object : DummyGUIVertexConsumer() {
|
||||||
|
override fun addChar(start: Vec2, end: Vec2, texture: AbstractTexture, uvStart: Vec2, uvEnd: Vec2, italic: Boolean, tint: RGBColor, options: GUIVertexOptions?) {
|
||||||
|
assertEquals(start, Vec2(10.0f, 13.5f)) // top spacing
|
||||||
|
assertEquals(end, Vec2(17.5f, 25.5f)) // start + width | start + height
|
||||||
|
|
||||||
|
// uv stays the same
|
||||||
|
assertEquals(uvStart, Vec2(0.1, 0.2))
|
||||||
|
assertEquals(uvEnd, Vec2(0.6, 0.7))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val char = DummyCodePointRenderer()
|
||||||
|
|
||||||
|
char.render(Vec2(10.0f, 12.0f), ChatColors.BLUE, false, false, false, 1.5f, consumer, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun shadow() {
|
||||||
|
val consumer = object : DummyGUIVertexConsumer() {
|
||||||
|
override fun addChar(start: Vec2, end: Vec2, index: Int) {
|
||||||
|
if (index == 1) return
|
||||||
|
assertEquals(start, Vec2(11.0f, 14.0f))
|
||||||
|
assertEquals(end, Vec2(16.0f, 22.0f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val char = DummyCodePointRenderer()
|
||||||
|
|
||||||
|
char.render(Vec2(10.0f, 12.0f), ChatColors.BLUE, true, false, false, 1.0f, consumer, null)
|
||||||
|
|
||||||
|
assertEquals(consumer.char, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bold() {
|
||||||
|
val consumer = object : DummyGUIVertexConsumer() {
|
||||||
|
override fun addChar(start: Vec2, end: Vec2, index: Int) {
|
||||||
|
if (index == 0) return
|
||||||
|
assertEquals(start, Vec2(10.5f, 13.0f))
|
||||||
|
assertEquals(end, Vec2(15.5f, 21.0f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val char = DummyCodePointRenderer()
|
||||||
|
|
||||||
|
char.render(Vec2(10.0f, 12.0f), ChatColors.BLUE, false, true, false, 1.0f, consumer, null)
|
||||||
|
|
||||||
|
assertEquals(consumer.char, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: ascent
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2023 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.gui.mesh
|
||||||
|
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
|
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
||||||
|
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.atlas.CodeTexturePart
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.ShaderIdentifiable
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.dummy.texture.DummyTexture
|
||||||
|
import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
|
||||||
|
|
||||||
|
open class DummyGUIVertexConsumer : GUIVertexConsumer {
|
||||||
|
override val whiteTexture = CodeTexturePart(texture = DummyTexture(minosoft("white")), uvStart = Vec2(0.0f, 0.0f), uvEnd = Vec2(0.001f, 0.001f), size = Vec2i(16, 16))
|
||||||
|
override val order: Array<Pair<Int, Int>> get() = Mesh.QUAD_TO_QUAD_ORDER
|
||||||
|
var char = 0
|
||||||
|
|
||||||
|
override fun addCache(cache: GUIMeshCache) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ensureSize(size: Int) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addVertex(position: Vec2, texture: ShaderIdentifiable, uv: Vec2, tint: RGBColor, options: GUIVertexOptions?) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addChar(start: Vec2, end: Vec2, texture: AbstractTexture, uvStart: Vec2, uvEnd: Vec2, italic: Boolean, tint: RGBColor, options: GUIVertexOptions?) {
|
||||||
|
addChar(start, end, this.char++)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun addChar(start: Vec2, end: Vec2, index: Int) {
|
||||||
|
TODO("Abstract")
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,6 @@ package de.bixilon.minosoft.gui.rendering.font
|
|||||||
import de.bixilon.kotlinglm.mat4x4.Mat4
|
import de.bixilon.kotlinglm.mat4x4.Mat4
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.component.ChatComponentRenderer
|
import de.bixilon.minosoft.gui.rendering.font.renderer.component.ChatComponentRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMeshCache
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMeshCache
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||||
@ -27,7 +26,7 @@ import de.bixilon.minosoft.gui.rendering.world.mesh.SingleWorldMesh
|
|||||||
|
|
||||||
|
|
||||||
class WorldGUIConsumer(val mesh: SingleWorldMesh, val transform: Mat4, val light: Int) : GUIVertexConsumer {
|
class WorldGUIConsumer(val mesh: SingleWorldMesh, val transform: Mat4, val light: Int) : GUIVertexConsumer {
|
||||||
override val context: RenderContext get() = mesh.context
|
override val whiteTexture = mesh.context.textureManager.whiteTexture
|
||||||
override val order: Array<Pair<Int, Int>> get() = mesh.order
|
override val order: Array<Pair<Int, Int>> get() = mesh.order
|
||||||
|
|
||||||
override fun addVertex(position: Vec2, texture: ShaderIdentifiable, uv: Vec2, tint: RGBColor, options: GUIVertexOptions?) {
|
override fun addVertex(position: Vec2, texture: ShaderIdentifiable, uv: Vec2, tint: RGBColor, options: GUIVertexOptions?) {
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.font.renderer.code
|
package de.bixilon.minosoft.gui.rendering.font.renderer.code
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.minosoft.data.text.formatting.TextFormatting
|
|
||||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||||
import de.bixilon.minosoft.gui.rendering.font.WorldGUIConsumer
|
import de.bixilon.minosoft.gui.rendering.font.WorldGUIConsumer
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||||
@ -25,10 +24,10 @@ interface CodePointRenderer {
|
|||||||
|
|
||||||
fun calculateWidth(scale: Float, shadow: Boolean): Float
|
fun calculateWidth(scale: Float, shadow: Boolean): Float
|
||||||
|
|
||||||
fun render(position: Vec2, color: RGBColor, shadow: Boolean, formatting: TextFormatting, consumer: GUIVertexConsumer, options: GUIVertexOptions?, scale: Float)
|
fun render(position: Vec2, color: RGBColor, shadow: Boolean, bold: Boolean, italic: Boolean, scale: Float, consumer: GUIVertexConsumer, options: GUIVertexOptions?)
|
||||||
|
|
||||||
fun render3d(consumer: WorldGUIConsumer, color: RGBColor, shadow: Boolean, formatting: TextFormatting, scale: Float): Float {
|
fun render3d(color: RGBColor, shadow: Boolean, bold: Boolean, italic: Boolean, scale: Float, consumer: WorldGUIConsumer): Float {
|
||||||
render(Vec2.EMPTY, color, shadow, formatting, consumer, null, scale)
|
render(Vec2.EMPTY, color, shadow, bold, italic, scale, consumer, null)
|
||||||
|
|
||||||
return calculateWidth(scale, shadow)
|
return calculateWidth(scale, shadow)
|
||||||
}
|
}
|
||||||
|
@ -14,15 +14,11 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.font.renderer.code
|
package de.bixilon.minosoft.gui.rendering.font.renderer.code
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.minosoft.data.text.formatting.FormattingCodes
|
|
||||||
import de.bixilon.minosoft.data.text.formatting.TextFormatting
|
|
||||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FontProperties
|
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FontProperties
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FormattingProperties.BOLD_OFFSET
|
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FormattingProperties.BOLD_OFFSET
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FormattingProperties.ITALIC_OFFSET
|
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FormattingProperties.SHADOW_COLOR
|
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FormattingProperties.SHADOW_COLOR
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FormattingProperties.SHADOW_OFFSET
|
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FormattingProperties.SHADOW_OFFSET
|
||||||
import de.bixilon.minosoft.gui.rendering.font.types.font.Font
|
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||||
@ -45,11 +41,11 @@ interface RasterizedCodePointRenderer : CodePointRenderer {
|
|||||||
return width * scale
|
return width * scale
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun render(position: Vec2, color: RGBColor, shadow: Boolean, formatting: TextFormatting, consumer: GUIVertexConsumer, options: GUIVertexOptions?, scale: Float) {
|
override fun render(position: Vec2, color: RGBColor, shadow: Boolean, bold: Boolean, italic: Boolean, scale: Float, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
||||||
if (shadow) {
|
if (shadow) {
|
||||||
render(position + (SHADOW_OFFSET * scale), color * SHADOW_COLOR, formatting, consumer, options, scale)
|
render(position + (SHADOW_OFFSET * scale), color * SHADOW_COLOR, bold, italic, scale, consumer, options)
|
||||||
}
|
}
|
||||||
render(position, color, formatting, consumer, options, scale)
|
render(position, color, bold, italic, scale, consumer, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateStart(base: Vec2, scale: Float): Vec2 {
|
fun calculateStart(base: Vec2, scale: Float): Vec2 {
|
||||||
@ -67,61 +63,19 @@ interface RasterizedCodePointRenderer : CodePointRenderer {
|
|||||||
return position
|
return position
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun render(position: Vec2, color: RGBColor, formatting: TextFormatting, consumer: GUIVertexConsumer, options: GUIVertexOptions?, scale: Float) {
|
private fun render(position: Vec2, color: RGBColor, bold: Boolean, italic: Boolean, scale: Float, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
||||||
var boldOffset = 0.0f
|
|
||||||
|
|
||||||
val bold = FormattingCodes.BOLD in formatting
|
|
||||||
val italic = FormattingCodes.ITALIC in formatting
|
|
||||||
|
|
||||||
if (bold) {
|
|
||||||
boldOffset = BOLD_OFFSET * scale
|
|
||||||
}
|
|
||||||
val charHeight = FontProperties.CHAR_BASE_HEIGHT * scale
|
|
||||||
val horizontalSpacing = Font.HORIZONTAL_SPACING * scale
|
|
||||||
val verticalSpacing = Font.VERTICAL_SPACING * scale
|
|
||||||
|
|
||||||
|
|
||||||
val startPosition = calculateStart(position, scale)
|
val startPosition = calculateStart(position, scale)
|
||||||
val endPosition = calculateEnd(startPosition, scale)
|
val endPosition = calculateEnd(startPosition, scale)
|
||||||
|
|
||||||
|
consumer.addChar(startPosition, endPosition, texture, uvStart, uvEnd, italic, color, options)
|
||||||
|
|
||||||
|
if (bold) {
|
||||||
consumer.addQuad(startPosition, endPosition, texture, uvStart, uvEnd, italic, color, options)
|
// render char another time but offset in x direction
|
||||||
|
val boldOffset = BOLD_OFFSET * scale
|
||||||
if (FormattingCodes.BOLD in formatting) {
|
consumer.addChar(
|
||||||
consumer.addQuad(startPosition + Vec2(boldOffset, 0.0f), endPosition + Vec2(boldOffset, 0.0f), texture, uvStart, uvEnd, italic, color, options)
|
start = startPosition + Vec2(boldOffset, 0.0f),
|
||||||
}
|
end = endPosition + Vec2(boldOffset, 0.0f),
|
||||||
val whiteTexture = consumer.context.textureManager.whiteTexture
|
texture, uvStart, uvEnd, italic, color, options)
|
||||||
|
|
||||||
if (FormattingCodes.STRIKETHROUGH in formatting) {
|
|
||||||
consumer.addQuad(startPosition + Vec2(-horizontalSpacing, charHeight / 2.0f - scale / 2), Vec2(endPosition.x + horizontalSpacing, startPosition.y + charHeight / 2.0f + scale / 2), whiteTexture.texture, whiteTexture.uvStart, whiteTexture.uvEnd, italic, color, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FormattingCodes.UNDERLINED in formatting) {
|
|
||||||
consumer.addQuad(startPosition + Vec2(-horizontalSpacing, charHeight), Vec2(endPosition.x + boldOffset + horizontalSpacing, startPosition.y + charHeight + verticalSpacing / 2.0f), whiteTexture.texture, whiteTexture.uvStart, whiteTexture.uvEnd, italic, color, options)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun GUIVertexConsumer.addQuad(start: Vec2, end: Vec2, texture: AbstractTexture, uvStart: Vec2, uvEnd: Vec2, italic: Boolean, tint: RGBColor, options: GUIVertexOptions?) {
|
|
||||||
val topOffset = if (italic) (end.y - start.y) / FontProperties.CHAR_BASE_HEIGHT * ITALIC_OFFSET else 0.0f
|
|
||||||
|
|
||||||
val positions = arrayOf(
|
|
||||||
Vec2(start.x + topOffset, start.y),
|
|
||||||
Vec2(end.x + topOffset, 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 this.order) {
|
|
||||||
addVertex(positions[vertexIndex], texture, texturePositions[textureIndex], tint, options)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,10 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
val color = text.color ?: ChatColors.WHITE
|
val color = text.color ?: ChatColors.WHITE
|
||||||
val shadow = renderInfo.shadow
|
val shadow = renderInfo.shadow
|
||||||
val bold: Boolean = text.formatting.contains(FormattingCodes.BOLD)
|
val bold: Boolean = text.formatting.contains(FormattingCodes.BOLD)
|
||||||
|
val italic: Boolean = text.formatting.contains(FormattingCodes.ITALIC)
|
||||||
|
|
||||||
// ToDo: Only 1 quad for the underline and the strikethrough
|
// ToDo: Only 1 quad for the underline and the strikethrough
|
||||||
|
// TODO: strike, underlined
|
||||||
|
|
||||||
var alignmentXOffset = 0.0f
|
var alignmentXOffset = 0.0f
|
||||||
var currentLineText = ""
|
var currentLineText = ""
|
||||||
@ -177,7 +179,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
// ToDo: Remove Font.HORIZONTAL_SPACING
|
// ToDo: Remove Font.HORIZONTAL_SPACING
|
||||||
}
|
}
|
||||||
|
|
||||||
consumer?.let { charData.render(letterOffset, color, shadow, text.formatting, it, options, renderInfo.scale) }
|
consumer?.let { charData.render(letterOffset, color, shadow, bold, italic, renderInfo.scale, it, options) }
|
||||||
|
|
||||||
if (consumer == null) {
|
if (consumer == null) {
|
||||||
currentLineText += char.toChar()
|
currentLineText += char.toChar()
|
||||||
@ -209,13 +211,16 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
|
|
||||||
val font = context.font[text.font]
|
val font = context.font[text.font]
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: strike, underlined
|
||||||
|
|
||||||
for (char in text.message.codePoints()) {
|
for (char in text.message.codePoints()) {
|
||||||
val data = font?.get(char) ?: context.font.default[char] ?: continue
|
val data = font?.get(char) ?: context.font.default[char] ?: continue
|
||||||
val expectedWidth = ((data.calculateWidth(scale, false) + Font.HORIZONTAL_SPACING) * scale).toInt()
|
val expectedWidth = ((data.calculateWidth(scale, false) + Font.HORIZONTAL_SPACING) * scale).toInt()
|
||||||
if (maxSize.x - offset.x < expectedWidth) { // ToDo
|
if (maxSize.x - offset.x < expectedWidth) { // ToDo
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val width = ((data.render3d(consumer, color, shadow = false, text.formatting, scale = scale) + Font.HORIZONTAL_SPACING) * scale).toInt()
|
val width = ((data.render3d(color, shadow = false, FormattingCodes.BOLD in text.formatting, FormattingCodes.ITALIC in text.formatting, scale = scale, consumer) + Font.HORIZONTAL_SPACING) * scale).toInt()
|
||||||
offset.x += width
|
offset.x += width
|
||||||
consumer.offset((width / ChatComponentRenderer.TEXT_BLOCK_RESOLUTION.toFloat()))
|
consumer.offset((width / ChatComponentRenderer.TEXT_BLOCK_RESOLUTION.toFloat()))
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.font.types.empty
|
package de.bixilon.minosoft.gui.rendering.font.types.empty
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.minosoft.data.text.formatting.TextFormatting
|
|
||||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.code.CodePointRenderer
|
import de.bixilon.minosoft.gui.rendering.font.renderer.code.CodePointRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FontProperties.MAX_CHAR_WIDTH
|
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FontProperties.MAX_CHAR_WIDTH
|
||||||
@ -31,5 +30,5 @@ data class EmptyCodeRenderer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun calculateWidth(scale: Float, shadow: Boolean): Float = width * scale
|
override fun calculateWidth(scale: Float, shadow: Boolean): Float = width * scale
|
||||||
override fun render(position: Vec2, color: RGBColor, shadow: Boolean, formatting: TextFormatting, consumer: GUIVertexConsumer, options: GUIVertexOptions?, scale: Float) = Unit
|
override fun render(position: Vec2, color: RGBColor, shadow: Boolean, bold: Boolean, italic: Boolean, scale: Float, consumer: GUIVertexConsumer, options: GUIVertexOptions?) = Unit
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ class AtlasElement(
|
|||||||
val end: Vec2i,
|
val end: Vec2i,
|
||||||
val slots: Int2ObjectOpenHashMap<AtlasSlot>,
|
val slots: Int2ObjectOpenHashMap<AtlasSlot>,
|
||||||
val areas: Map<String, AtlasArea>,
|
val areas: Map<String, AtlasArea>,
|
||||||
) : TextureLike {
|
) : TexturePart {
|
||||||
override val size: Vec2i = end - start
|
override val size: Vec2i = end - start
|
||||||
override lateinit var uvStart: Vec2
|
override lateinit var uvStart: Vec2
|
||||||
override lateinit var uvEnd: Vec2
|
override lateinit var uvEnd: Vec2
|
||||||
|
@ -17,9 +17,9 @@ import de.bixilon.kotlinglm.vec2.Vec2
|
|||||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||||
|
|
||||||
class TextureLikeTexture(
|
class CodeTexturePart(
|
||||||
override val texture: AbstractTexture,
|
override val texture: AbstractTexture,
|
||||||
override val uvStart: Vec2,
|
override val uvStart: Vec2,
|
||||||
override val uvEnd: Vec2,
|
override val uvEnd: Vec2,
|
||||||
override val size: Vec2i,
|
override val size: Vec2i,
|
||||||
) : TextureLike
|
) : TexturePart
|
@ -17,7 +17,7 @@ import de.bixilon.kotlinglm.vec2.Vec2
|
|||||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||||
|
|
||||||
interface TextureLike {
|
interface TexturePart {
|
||||||
val texture: AbstractTexture
|
val texture: AbstractTexture
|
||||||
val uvStart: Vec2
|
val uvStart: Vec2
|
||||||
val uvEnd: Vec2
|
val uvEnd: Vec2
|
@ -18,7 +18,7 @@ import de.bixilon.kotlinglm.vec2.Vec2i
|
|||||||
import de.bixilon.minosoft.data.text.formatting.color.ChatColors
|
import de.bixilon.minosoft.data.text.formatting.color.ChatColors
|
||||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.atlas.TextureLike
|
import de.bixilon.minosoft.gui.rendering.gui.atlas.TexturePart
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMesh
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMesh
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||||
@ -28,11 +28,11 @@ import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
|||||||
|
|
||||||
open class AtlasImageElement(
|
open class AtlasImageElement(
|
||||||
guiRenderer: GUIRenderer,
|
guiRenderer: GUIRenderer,
|
||||||
textureLike: TextureLike?,
|
texturePart: TexturePart?,
|
||||||
size: Vec2i = textureLike?.size ?: Vec2i.EMPTY,
|
size: Vec2i = texturePart?.size ?: Vec2i.EMPTY,
|
||||||
tint: RGBColor = ChatColors.WHITE,
|
tint: RGBColor = ChatColors.WHITE,
|
||||||
) : Element(guiRenderer, GUIMesh.GUIMeshStruct.FLOATS_PER_VERTEX * 6) {
|
) : Element(guiRenderer, GUIMesh.GUIMeshStruct.FLOATS_PER_VERTEX * 6) {
|
||||||
var texture: AbstractTexture? = textureLike?.texture
|
var texture: AbstractTexture? = texturePart?.texture
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
cacheUpToDate = false
|
cacheUpToDate = false
|
||||||
@ -67,7 +67,7 @@ open class AtlasImageElement(
|
|||||||
cacheUpToDate = false
|
cacheUpToDate = false
|
||||||
}
|
}
|
||||||
|
|
||||||
var textureLike: TextureLike? = textureLike
|
var texturePart: TexturePart? = texturePart
|
||||||
set(value) {
|
set(value) {
|
||||||
if (field === value) {
|
if (field === value) {
|
||||||
return
|
return
|
||||||
@ -87,7 +87,7 @@ open class AtlasImageElement(
|
|||||||
|
|
||||||
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
override fun forceRender(offset: Vec2i, consumer: GUIVertexConsumer, options: GUIVertexOptions?) {
|
||||||
val texture = texture ?: return
|
val texture = texture ?: return
|
||||||
val textureLike = textureLike ?: return
|
val textureLike = texturePart ?: return
|
||||||
consumer.addQuad(offset, offset + size, texture, uvStart ?: textureLike.uvStart, uvEnd ?: textureLike.uvEnd, tint, options)
|
consumer.addQuad(offset, offset + size, texture, uvStart ?: textureLike.uvStart, uvEnd ?: textureLike.uvEnd, tint, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ class GUIMesh(
|
|||||||
val halfSize: Vec2,
|
val halfSize: Vec2,
|
||||||
data: AbstractFloatList,
|
data: AbstractFloatList,
|
||||||
) : Mesh(context, GUIMeshStruct, initialCacheSize = 40000, clearOnLoad = false, data = data), GUIVertexConsumer {
|
) : Mesh(context, GUIMeshStruct, initialCacheSize = 40000, clearOnLoad = false, data = data), GUIVertexConsumer {
|
||||||
|
override val whiteTexture = context.textureManager.whiteTexture
|
||||||
|
|
||||||
override fun addVertex(position: Vec2, texture: ShaderIdentifiable, uv: Vec2, tint: RGBColor, options: GUIVertexOptions?) {
|
override fun addVertex(position: Vec2, texture: ShaderIdentifiable, uv: Vec2, tint: RGBColor, options: GUIVertexOptions?) {
|
||||||
addVertex(data, halfSize, position, texture, uv, tint, options)
|
addVertex(data, halfSize, position, texture, uv, tint, options)
|
||||||
|
@ -25,10 +25,12 @@ import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
|||||||
class GUIMeshCache(
|
class GUIMeshCache(
|
||||||
var halfSize: Vec2,
|
var halfSize: Vec2,
|
||||||
override val order: Array<Pair<Int, Int>>,
|
override val order: Array<Pair<Int, Int>>,
|
||||||
override val context: RenderContext,
|
val context: RenderContext,
|
||||||
initialCacheSize: Int = 1000,
|
initialCacheSize: Int = 1000,
|
||||||
var data: AbstractFloatList = HeapArrayFloatList(initialCacheSize),
|
var data: AbstractFloatList = HeapArrayFloatList(initialCacheSize),
|
||||||
) : GUIVertexConsumer {
|
) : GUIVertexConsumer {
|
||||||
|
override val whiteTexture = context.textureManager.whiteTexture
|
||||||
|
|
||||||
var revision: Long = 0
|
var revision: Long = 0
|
||||||
var offset: Vec2i = Vec2i.EMPTY
|
var offset: Vec2i = Vec2i.EMPTY
|
||||||
var options: GUIVertexOptions? = null
|
var options: GUIVertexOptions? = null
|
||||||
|
@ -16,12 +16,15 @@ package de.bixilon.minosoft.gui.rendering.gui.mesh
|
|||||||
import de.bixilon.kotlinglm.vec2.Vec2
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FontProperties
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.atlas.TextureLike
|
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FormattingProperties
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.atlas.CodeTexturePart
|
||||||
|
import de.bixilon.minosoft.gui.rendering.gui.atlas.TexturePart
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.ShaderIdentifiable
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.ShaderIdentifiable
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||||
|
|
||||||
interface GUIVertexConsumer {
|
interface GUIVertexConsumer {
|
||||||
val context: RenderContext
|
val whiteTexture: CodeTexturePart
|
||||||
val order: Array<Pair<Int, Int>>
|
val order: Array<Pair<Int, Int>>
|
||||||
|
|
||||||
fun addVertex(position: Vec2, texture: ShaderIdentifiable, uv: Vec2, tint: RGBColor, options: GUIVertexOptions?)
|
fun addVertex(position: Vec2, texture: ShaderIdentifiable, uv: Vec2, tint: RGBColor, options: GUIVertexOptions?)
|
||||||
@ -67,14 +70,36 @@ interface GUIVertexConsumer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addQuad(start: Vec2, end: Vec2, texture: TextureLike, tint: RGBColor, options: GUIVertexOptions?) {
|
fun addQuad(start: Vec2, end: Vec2, texture: TexturePart, tint: RGBColor, options: GUIVertexOptions?) {
|
||||||
addQuad(start, end, texture.texture, texture.uvStart, texture.uvEnd, tint, options)
|
addQuad(start, end, texture.texture, texture.uvStart, texture.uvEnd, tint, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addQuad(start: Vec2i, end: Vec2i, texture: TextureLike, tint: RGBColor, options: GUIVertexOptions?) {
|
fun addQuad(start: Vec2i, end: Vec2i, texture: TexturePart, tint: RGBColor, options: GUIVertexOptions?) {
|
||||||
addQuad(start, end, texture.texture, texture.uvStart, texture.uvEnd, tint, options)
|
addQuad(start, end, texture.texture, texture.uvStart, texture.uvEnd, tint, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun addChar(start: Vec2, end: Vec2, texture: AbstractTexture, uvStart: Vec2, uvEnd: Vec2, italic: Boolean, tint: RGBColor, options: GUIVertexOptions?) {
|
||||||
|
val topOffset = if (italic) (end.y - start.y) / FontProperties.CHAR_BASE_HEIGHT * FormattingProperties.ITALIC_OFFSET else 0.0f
|
||||||
|
|
||||||
|
val positions = arrayOf(
|
||||||
|
Vec2(start.x + topOffset, start.y),
|
||||||
|
Vec2(end.x + topOffset, 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 this.order) {
|
||||||
|
addVertex(positions[vertexIndex], texture, texturePositions[textureIndex], tint, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun addCache(cache: GUIMeshCache)
|
fun addCache(cache: GUIMeshCache)
|
||||||
|
|
||||||
fun ensureSize(size: Int)
|
fun ensureSize(size: Int)
|
||||||
|
@ -17,7 +17,7 @@ import de.bixilon.kotlinglm.vec2.Vec2
|
|||||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.atlas.TextureLikeTexture
|
import de.bixilon.minosoft.gui.rendering.gui.atlas.CodeTexturePart
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader
|
import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.shader.ShaderUniforms
|
import de.bixilon.minosoft.gui.rendering.system.base.shader.ShaderUniforms
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.dynamic.DynamicTextureArray
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.dynamic.DynamicTextureArray
|
||||||
@ -32,7 +32,7 @@ abstract class TextureManager {
|
|||||||
|
|
||||||
lateinit var debugTexture: AbstractTexture
|
lateinit var debugTexture: AbstractTexture
|
||||||
private set
|
private set
|
||||||
lateinit var whiteTexture: TextureLikeTexture
|
lateinit var whiteTexture: CodeTexturePart
|
||||||
private set
|
private set
|
||||||
lateinit var skins: SkinManager
|
lateinit var skins: SkinManager
|
||||||
private set
|
private set
|
||||||
@ -42,7 +42,7 @@ abstract class TextureManager {
|
|||||||
throw IllegalStateException("Already initialized!")
|
throw IllegalStateException("Already initialized!")
|
||||||
}
|
}
|
||||||
debugTexture = staticTextures.createTexture(RenderConstants.DEBUG_TEXTURE_RESOURCE_LOCATION)
|
debugTexture = staticTextures.createTexture(RenderConstants.DEBUG_TEXTURE_RESOURCE_LOCATION)
|
||||||
whiteTexture = TextureLikeTexture(texture = staticTextures.createTexture(minosoft("white").texture()), uvStart = Vec2(0.0f, 0.0f), uvEnd = Vec2(0.001f, 0.001f), size = Vec2i(16, 16))
|
whiteTexture = CodeTexturePart(texture = staticTextures.createTexture(minosoft("white").texture()), uvStart = Vec2(0.0f, 0.0f), uvEnd = Vec2(0.001f, 0.001f), size = Vec2i(16, 16))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initializeSkins(connection: PlayConnection) {
|
fun initializeSkins(connection: PlayConnection) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user