mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-15 10:25:06 -04:00
refactor font rendering more
This commit is contained in:
parent
761ea0a582
commit
d9c74a71d7
@ -57,6 +57,7 @@ class BaseComponent : ChatComponent {
|
|||||||
json["strikethrough"]?.toBoolean()?.let { formatting[FormattingCodes.STRIKETHROUGH] = it }
|
json["strikethrough"]?.toBoolean()?.let { formatting[FormattingCodes.STRIKETHROUGH] = it }
|
||||||
json["obfuscated"]?.toBoolean()?.let { formatting[FormattingCodes.OBFUSCATED] = it }
|
json["obfuscated"]?.toBoolean()?.let { formatting[FormattingCodes.OBFUSCATED] = it }
|
||||||
|
|
||||||
|
val font = json["font"]?.toResourceLocation() ?: parent?.font
|
||||||
val clickEvent = json["clickEvent", "click_event"]?.toJsonObject()?.let { click -> ClickEvents.build(click, restricted) } ?: parent?.clickEvent
|
val clickEvent = json["clickEvent", "click_event"]?.toJsonObject()?.let { click -> ClickEvents.build(click, restricted) } ?: parent?.clickEvent
|
||||||
val hoverEvent = json["hoverEvent", "hover_event"]?.toJsonObject()?.let { hover -> HoverEvents.build(hover, restricted) } ?: parent?.hoverEvent
|
val hoverEvent = json["hoverEvent", "hover_event"]?.toJsonObject()?.let { hover -> HoverEvents.build(hover, restricted) } ?: parent?.hoverEvent
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ class BaseComponent : ChatComponent {
|
|||||||
message = text,
|
message = text,
|
||||||
color = color,
|
color = color,
|
||||||
formatting = formatting,
|
formatting = formatting,
|
||||||
|
font = font,
|
||||||
clickEvent = clickEvent,
|
clickEvent = clickEvent,
|
||||||
hoverEvent = hoverEvent,
|
hoverEvent = hoverEvent,
|
||||||
)
|
)
|
||||||
|
@ -50,15 +50,15 @@ object LegacyComponentReader {
|
|||||||
}
|
}
|
||||||
if (text.isNotEmpty()) {
|
if (text.isNotEmpty()) {
|
||||||
// an url follows, push the previous part
|
// an url follows, push the previous part
|
||||||
this += TextComponent(text, sequence.color, sequence.formatting.copy(), parent?.clickEvent, parent?.hoverEvent)
|
this += TextComponent(text, sequence.color, sequence.formatting.copy(), null, parent?.clickEvent, parent?.hoverEvent)
|
||||||
text.clear()
|
text.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
this += TextComponent(part, sequence.color, sequence.formatting.copy(), parent?.clickEvent ?: event, parent?.hoverEvent)
|
this += TextComponent(part, sequence.color, sequence.formatting.copy(), null, parent?.clickEvent ?: event, parent?.hoverEvent)
|
||||||
}
|
}
|
||||||
if (text.isNotEmpty()) {
|
if (text.isNotEmpty()) {
|
||||||
// data that was not pushed yet
|
// data that was not pushed yet
|
||||||
this += TextComponent(text, sequence.color, sequence.formatting.copy(), parent?.clickEvent, parent?.hoverEvent)
|
this += TextComponent(text, sequence.color, sequence.formatting.copy(), null, parent?.clickEvent, parent?.hoverEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
sequence.reset() // clear it up again for next usage
|
sequence.reset() // clear it up again for next usage
|
||||||
|
@ -14,6 +14,7 @@ package de.bixilon.minosoft.data.text
|
|||||||
|
|
||||||
import de.bixilon.kutil.json.MutableJsonObject
|
import de.bixilon.kutil.json.MutableJsonObject
|
||||||
import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfileManager
|
import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfileManager
|
||||||
|
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||||
import de.bixilon.minosoft.data.text.events.click.ClickEvent
|
import de.bixilon.minosoft.data.text.events.click.ClickEvent
|
||||||
import de.bixilon.minosoft.data.text.events.hover.HoverEvent
|
import de.bixilon.minosoft.data.text.events.hover.HoverEvent
|
||||||
import de.bixilon.minosoft.data.text.formatting.FormattingCodes
|
import de.bixilon.minosoft.data.text.formatting.FormattingCodes
|
||||||
@ -37,6 +38,7 @@ open class TextComponent(
|
|||||||
message: Any? = "",
|
message: Any? = "",
|
||||||
override var color: RGBColor? = null,
|
override var color: RGBColor? = null,
|
||||||
override val formatting: TextFormatting = TextFormatting(),
|
override val formatting: TextFormatting = TextFormatting(),
|
||||||
|
var font: ResourceLocation? = null,
|
||||||
var clickEvent: ClickEvent? = null,
|
var clickEvent: ClickEvent? = null,
|
||||||
var hoverEvent: HoverEvent? = null,
|
var hoverEvent: HoverEvent? = null,
|
||||||
) : ChatComponent, TextStyle {
|
) : ChatComponent, TextStyle {
|
||||||
@ -224,7 +226,7 @@ open class TextComponent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun copy(): ChatComponent {
|
override fun copy(): ChatComponent {
|
||||||
return TextComponent(message, color, formatting.copy(), clickEvent, hoverEvent)
|
return TextComponent(message, color, formatting.copy(), font, clickEvent, hoverEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
|
@ -14,13 +14,7 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.font
|
package de.bixilon.minosoft.gui.rendering.font
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
|
||||||
import de.bixilon.kutil.math.simple.FloatMath.ceil
|
|
||||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
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.GUIVertexOptions
|
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||||
|
|
||||||
@Deprecated("renderer")
|
@Deprecated("renderer")
|
||||||
@ -31,106 +25,4 @@ class CharData(
|
|||||||
val scaledWidth: Int,
|
val scaledWidth: Int,
|
||||||
var uvStart: Vec2,
|
var uvStart: Vec2,
|
||||||
var uvEnd: Vec2,
|
var uvEnd: Vec2,
|
||||||
) {
|
)
|
||||||
|
|
||||||
fun postInit() {
|
|
||||||
if (texture == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
uvStart = uvStart * texture.textureArrayUV
|
|
||||||
uvEnd = uvEnd * texture.textureArrayUV
|
|
||||||
}
|
|
||||||
|
|
||||||
fun render(position: Vec2i, color: RGBColor, shadow: Boolean, italic: Boolean, bold: Boolean, strikethrough: Boolean, underlined: Boolean, consumer: GUIVertexConsumer, options: GUIVertexOptions?, scale: Float) {
|
|
||||||
if (shadow) {
|
|
||||||
_render(position, color, true, italic, bold, strikethrough, underlined, consumer, options, scale)
|
|
||||||
}
|
|
||||||
_render(position, color, false, italic, bold, strikethrough, underlined, consumer, options, scale)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun GUIVertexConsumer.addQuad(start: Vec2, end: Vec2, texture: AbstractTexture, uvStart: Vec2, uvEnd: Vec2, italic: Boolean, tint: RGBColor, options: GUIVertexOptions?) {
|
|
||||||
val italicOffset = if (italic) (end.y - start.y) / Font.CHAR_HEIGHT.toFloat() * ITALIC_OFFSET else 0.0f
|
|
||||||
|
|
||||||
val positions = arrayOf(
|
|
||||||
Vec2(start.x + italicOffset, start.y),
|
|
||||||
Vec2(end.x + italicOffset, 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun _render(position: Vec2i, color: RGBColor, shadow: Boolean, italic: Boolean, bold: Boolean, strikethrough: Boolean, underlined: Boolean, vertexConsumer: GUIVertexConsumer, options: GUIVertexOptions?, scale: Float) {
|
|
||||||
if (texture == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var color = color
|
|
||||||
|
|
||||||
var shadowOffset = 0.0f
|
|
||||||
if (shadow) {
|
|
||||||
shadowOffset = SHADOW_OFFSET
|
|
||||||
color *= 0.25f
|
|
||||||
}
|
|
||||||
|
|
||||||
var boldOffset = 0.0f
|
|
||||||
|
|
||||||
if (bold) {
|
|
||||||
boldOffset = BOLD_OFFSET * scale
|
|
||||||
}
|
|
||||||
val charHeight = Font.CHAR_HEIGHT * scale
|
|
||||||
val horizontalSpacing = Font.HORIZONTAL_SPACING * scale
|
|
||||||
val verticalSpacing = Font.VERTICAL_SPACING * scale
|
|
||||||
|
|
||||||
|
|
||||||
val startPosition = Vec2(position) + (shadowOffset * scale)
|
|
||||||
val endPosition = startPosition + (Vec2(scaledWidth * scale, charHeight))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vertexConsumer.addQuad(startPosition, endPosition, texture, uvStart, uvEnd, italic, color, options)
|
|
||||||
|
|
||||||
if (bold) {
|
|
||||||
vertexConsumer.addQuad(startPosition + Vec2(boldOffset, 0.0f), endPosition + Vec2(boldOffset, 0.0f), texture, uvStart, uvEnd, italic, color, options)
|
|
||||||
}
|
|
||||||
val whiteTexture = context.textureManager.whiteTexture
|
|
||||||
|
|
||||||
if (strikethrough) {
|
|
||||||
vertexConsumer.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 (underlined) {
|
|
||||||
vertexConsumer.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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToDo: Obfuscated
|
|
||||||
}
|
|
||||||
|
|
||||||
fun calculateWidth(scale: Float, shadow: Boolean): Int {
|
|
||||||
var width = scaledWidth.toFloat()
|
|
||||||
if (shadow) {
|
|
||||||
width += SHADOW_OFFSET
|
|
||||||
}
|
|
||||||
|
|
||||||
return (width * scale).ceil
|
|
||||||
}
|
|
||||||
|
|
||||||
fun render3d(consumer: WorldGUIConsumer, color: RGBColor, shadow: Boolean, italic: Boolean, bold: Boolean, strikethrough: Boolean, underlined: Boolean, scale: Float): Float {
|
|
||||||
render(Vec2i(0, 0), color, shadow, italic, bold, strikethrough, underlined, consumer, null, scale)
|
|
||||||
return scaledWidth.toFloat()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val ITALIC_OFFSET = 2.5f
|
|
||||||
const val SHADOW_OFFSET = 1.0f
|
|
||||||
const val BOLD_OFFSET = 0.5f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -16,6 +16,7 @@ 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
|
||||||
@ -26,6 +27,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 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?) {
|
||||||
|
@ -16,18 +16,31 @@ package de.bixilon.minosoft.gui.rendering.font.manager
|
|||||||
import de.bixilon.kutil.latch.AbstractLatch
|
import de.bixilon.kutil.latch.AbstractLatch
|
||||||
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
|
import de.bixilon.minosoft.gui.rendering.font.loader.DefaultFontIndices
|
||||||
|
import de.bixilon.minosoft.gui.rendering.font.loader.FontLoader
|
||||||
import de.bixilon.minosoft.gui.rendering.font.types.FontType
|
import de.bixilon.minosoft.gui.rendering.font.types.FontType
|
||||||
|
import de.bixilon.minosoft.gui.rendering.font.types.PostInitFontType
|
||||||
|
import de.bixilon.minosoft.gui.rendering.font.types.font.EmptyFont
|
||||||
import de.bixilon.minosoft.gui.rendering.font.types.font.Font
|
import de.bixilon.minosoft.gui.rendering.font.types.font.Font
|
||||||
|
|
||||||
class FontManager {
|
class FontManager(
|
||||||
val default: FontType
|
val default: FontType,
|
||||||
|
) {
|
||||||
|
|
||||||
fun postInit(latch: AbstractLatch)
|
fun postInit(latch: AbstractLatch) {
|
||||||
|
if (default is PostInitFontType) {
|
||||||
|
default.postInit(latch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
operator fun get(font: ResourceLocation): Font?
|
operator fun get(font: ResourceLocation?): Font? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun create(context: RenderContext, latch: AbstractLatch): FontManager {}
|
fun create(context: RenderContext, latch: AbstractLatch): FontManager {
|
||||||
|
val font = FontLoader.load(context, DefaultFontIndices.DEFAULT, latch)
|
||||||
|
|
||||||
|
return FontManager(font ?: EmptyFont)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Font that is shifted vertically
|
||||||
|
* See the great explanation of @Suragch at https://stackoverflow.com/questions/27631736/meaning-of-top-ascent-baseline-descent-bottom-and-leading-in-androids-font
|
||||||
|
*/
|
||||||
|
interface AscentedCodePointRenderer : CodePointRenderer {
|
||||||
|
val descent: Float
|
||||||
|
val ascent: Float
|
||||||
|
}
|
@ -16,12 +16,20 @@ 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.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.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.util.vec.vec2.Vec2Util.EMPTY
|
||||||
|
|
||||||
interface CodePointRenderer {
|
interface CodePointRenderer {
|
||||||
|
|
||||||
fun calculateWidth(scale: Float, shadow: Boolean): Float
|
fun calculateWidth(scale: Float, shadow: Boolean): Float
|
||||||
|
|
||||||
fun render(position: Vec2, color: RGBColor, formatting: TextFormatting, consumer: GUIVertexConsumer, options: GUIVertexOptions?, scale: Float)
|
fun render(position: Vec2, color: RGBColor, shadow: Boolean, formatting: TextFormatting, consumer: GUIVertexConsumer, options: GUIVertexOptions?, scale: Float)
|
||||||
|
|
||||||
|
fun render3d(consumer: WorldGUIConsumer, color: RGBColor, shadow: Boolean, formatting: TextFormatting, scale: Float): Float {
|
||||||
|
render(Vec2.EMPTY, color, shadow, formatting, consumer, null, scale)
|
||||||
|
|
||||||
|
return calculateWidth(scale, shadow)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* 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.text.formatting.FormattingCodes
|
||||||
|
import de.bixilon.minosoft.data.text.formatting.TextFormatting
|
||||||
|
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.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_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.GUIVertexOptions
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||||
|
|
||||||
|
interface RasterizedCodePointRenderer : CodePointRenderer {
|
||||||
|
val texture: AbstractTexture
|
||||||
|
|
||||||
|
val uvStart: Vec2
|
||||||
|
val uvEnd: Vec2
|
||||||
|
|
||||||
|
val width: Float
|
||||||
|
|
||||||
|
|
||||||
|
override fun calculateWidth(scale: Float, shadow: Boolean): Float {
|
||||||
|
var width = width
|
||||||
|
if (shadow) {
|
||||||
|
width += SHADOW_OFFSET
|
||||||
|
}
|
||||||
|
|
||||||
|
return width * scale
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(position: Vec2, color: RGBColor, shadow: Boolean, formatting: TextFormatting, consumer: GUIVertexConsumer, options: GUIVertexOptions?, scale: Float) {
|
||||||
|
if (shadow) {
|
||||||
|
render(position + (SHADOW_OFFSET * scale), color * SHADOW_COLOR, formatting, consumer, options, scale)
|
||||||
|
}
|
||||||
|
render(position, color, formatting, consumer, options, scale)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calculateStart(base: Vec2, scale: Float): Vec2 {
|
||||||
|
val position = Vec2(base)
|
||||||
|
position.y += (FontProperties.CHAR_SPACING_TOP * scale)
|
||||||
|
|
||||||
|
return position
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calculateEnd(start: Vec2, scale: Float): Vec2 {
|
||||||
|
val position = Vec2(start)
|
||||||
|
position.y += (FontProperties.CHAR_BASE_HEIGHT * scale)
|
||||||
|
position.x += width * scale
|
||||||
|
|
||||||
|
return position
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun render(position: Vec2, color: RGBColor, formatting: TextFormatting, consumer: GUIVertexConsumer, options: GUIVertexOptions?, scale: Float) {
|
||||||
|
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 endPosition = calculateEnd(startPosition, scale)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
consumer.addQuad(startPosition, endPosition, texture, uvStart, uvEnd, italic, color, options)
|
||||||
|
|
||||||
|
if (FormattingCodes.BOLD in formatting) {
|
||||||
|
consumer.addQuad(startPosition + Vec2(boldOffset, 0.0f), endPosition + Vec2(boldOffset, 0.0f), texture, uvStart, uvEnd, italic, color, options)
|
||||||
|
}
|
||||||
|
val whiteTexture = consumer.context.textureManager.whiteTexture
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.font.renderer.component
|
package de.bixilon.minosoft.gui.rendering.font.renderer.component
|
||||||
|
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
import de.bixilon.minosoft.data.text.BaseComponent
|
import de.bixilon.minosoft.data.text.BaseComponent
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
@ -24,7 +25,7 @@ import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
|||||||
|
|
||||||
object BaseComponentRenderer : ChatComponentRenderer<BaseComponent> {
|
object BaseComponentRenderer : ChatComponentRenderer<BaseComponent> {
|
||||||
|
|
||||||
override fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, element: Element, context: RenderContext, consumer: GUIVertexConsumer?, options: GUIVertexOptions?, renderInfo: TextRenderInfo, text: BaseComponent): Boolean {
|
override fun render(initialOffset: Vec2, offset: Vec2, size: Vec2, element: Element, context: RenderContext, consumer: GUIVertexConsumer?, options: GUIVertexOptions?, renderInfo: TextRenderInfo, text: BaseComponent): Boolean {
|
||||||
for (part in text.parts) {
|
for (part in text.parts) {
|
||||||
if (ChatComponentRenderer.render(initialOffset, offset, size, element, context, consumer, options, renderInfo, part)) {
|
if (ChatComponentRenderer.render(initialOffset, offset, size, element, context, consumer, options, renderInfo, part)) {
|
||||||
return true
|
return true
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.font.renderer.component
|
package de.bixilon.minosoft.gui.rendering.font.renderer.component
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.mat4x4.Mat4
|
import de.bixilon.kotlinglm.mat4x4.Mat4
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
import de.bixilon.kotlinglm.vec3.Vec3
|
import de.bixilon.kotlinglm.vec3.Vec3
|
||||||
import de.bixilon.minosoft.data.text.BaseComponent
|
import de.bixilon.minosoft.data.text.BaseComponent
|
||||||
@ -35,7 +36,7 @@ interface ChatComponentRenderer<T : ChatComponent> {
|
|||||||
/**
|
/**
|
||||||
* Returns true if the text exceeded the maximum size
|
* Returns true if the text exceeded the maximum size
|
||||||
*/
|
*/
|
||||||
fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, element: Element, context: RenderContext, consumer: GUIVertexConsumer?, options: GUIVertexOptions?, renderInfo: TextRenderInfo, text: T): Boolean
|
fun render(initialOffset: Vec2, offset: Vec2, size: Vec2, element: Element, context: RenderContext, consumer: GUIVertexConsumer?, options: GUIVertexOptions?, renderInfo: TextRenderInfo, text: T): Boolean
|
||||||
|
|
||||||
fun render3dFlat(context: RenderContext, offset: Vec2i, scale: Float, maxSize: Vec2i, consumer: WorldGUIConsumer, text: T, light: Int)
|
fun render3dFlat(context: RenderContext, offset: Vec2i, scale: Float, maxSize: Vec2i, consumer: WorldGUIConsumer, text: T, light: Int)
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ interface ChatComponentRenderer<T : ChatComponent> {
|
|||||||
companion object : ChatComponentRenderer<ChatComponent> {
|
companion object : ChatComponentRenderer<ChatComponent> {
|
||||||
const val TEXT_BLOCK_RESOLUTION = 128
|
const val TEXT_BLOCK_RESOLUTION = 128
|
||||||
|
|
||||||
override fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, element: Element, context: RenderContext, consumer: GUIVertexConsumer?, options: GUIVertexOptions?, renderInfo: TextRenderInfo, text: ChatComponent): Boolean {
|
override fun render(initialOffset: Vec2, offset: Vec2, size: Vec2, element: Element, context: RenderContext, consumer: GUIVertexConsumer?, options: GUIVertexOptions?, renderInfo: TextRenderInfo, text: ChatComponent): Boolean {
|
||||||
return when (text) {
|
return when (text) {
|
||||||
is BaseComponent -> BaseComponentRenderer.render(initialOffset, offset, size, element, context, consumer, options, renderInfo, text)
|
is BaseComponent -> BaseComponentRenderer.render(initialOffset, offset, size, element, context, consumer, options, renderInfo, text)
|
||||||
is TextComponent -> TextComponentRenderer.render(initialOffset, offset, size, element, context, consumer, options, renderInfo, text)
|
is TextComponent -> TextComponentRenderer.render(initialOffset, offset, size, element, context, consumer, options, renderInfo, text)
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.font.renderer.component
|
package de.bixilon.minosoft.gui.rendering.font.renderer.component
|
||||||
|
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
import de.bixilon.minosoft.data.text.TextComponent
|
import de.bixilon.minosoft.data.text.TextComponent
|
||||||
import de.bixilon.minosoft.data.text.formatting.FormattingCodes
|
import de.bixilon.minosoft.data.text.formatting.FormattingCodes
|
||||||
@ -29,22 +30,20 @@ import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
|||||||
|
|
||||||
object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
||||||
|
|
||||||
override fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, element: Element, context: RenderContext, consumer: GUIVertexConsumer?, options: GUIVertexOptions?, renderInfo: TextRenderInfo, text: TextComponent): Boolean {
|
override fun render(initialOffset: Vec2, offset: Vec2, size: Vec2, element: Element, context: RenderContext, consumer: GUIVertexConsumer?, options: GUIVertexOptions?, renderInfo: TextRenderInfo, text: TextComponent): Boolean {
|
||||||
if (text.message.isEmpty()) {
|
if (text.message.isEmpty()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
val font = context.font[text.font]
|
||||||
val elementMaxSize = element.maxSize
|
val elementMaxSize = element.maxSize
|
||||||
val elementSize = element.size
|
val elementSize = element.size
|
||||||
val color = text.color ?: ChatColors.WHITE
|
val color = text.color ?: ChatColors.WHITE
|
||||||
val shadow = renderInfo.shadow
|
val shadow = renderInfo.shadow
|
||||||
val italic: Boolean = text.formatting.contains(FormattingCodes.ITALIC)
|
|
||||||
val bold: Boolean = text.formatting.contains(FormattingCodes.BOLD)
|
val bold: Boolean = text.formatting.contains(FormattingCodes.BOLD)
|
||||||
val strikethrough: Boolean = text.formatting.contains(FormattingCodes.STRIKETHROUGH)
|
|
||||||
val underlined: Boolean = text.formatting.contains(FormattingCodes.UNDERLINED)
|
|
||||||
|
|
||||||
// ToDo: Only 1 quad for the underline and the strikethrough
|
// ToDo: Only 1 quad for the underline and the strikethrough
|
||||||
|
|
||||||
var alignmentXOffset = 0
|
var alignmentXOffset = 0.0f
|
||||||
var currentLineText = ""
|
var currentLineText = ""
|
||||||
if (size.x > elementMaxSize.x || size.y > elementMaxSize.y) {
|
if (size.x > elementMaxSize.x || size.y > elementMaxSize.y) {
|
||||||
// The size is already bigger/equals the maximum size
|
// The size is already bigger/equals the maximum size
|
||||||
@ -65,15 +64,15 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
|
|
||||||
fun applyOffset() {
|
fun applyOffset() {
|
||||||
val lastLine = renderInfo.lines.getOrNull(renderInfo.lineIndex)
|
val lastLine = renderInfo.lines.getOrNull(renderInfo.lineIndex)
|
||||||
if (consumer == null && offset.x == initialOffset.x + renderInfo.charMargin && (lastLine == null || lastLine.width != 0)) {
|
if (consumer == null && offset.x == initialOffset.x + renderInfo.charMargin && (lastLine == null || lastLine.width != 0.0f)) {
|
||||||
// preparing phase
|
// preparing phase
|
||||||
renderInfo.lines += TextLineInfo()
|
renderInfo.lines += TextLineInfo()
|
||||||
} else {
|
} else {
|
||||||
alignmentXOffset = renderInfo.fontAlignment.getOffset(elementSize.x, renderInfo.currentLine.width)
|
alignmentXOffset = renderInfo.fontAlignment.getOffset(elementSize.x.toFloat(), renderInfo.currentLine.width)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addY(height: Int): Boolean {
|
fun addY(height: Float): Boolean {
|
||||||
val nextY = offset.y + height
|
val nextY = offset.y + height
|
||||||
val nextSizeY = nextY - initialOffset.y + renderInfo.charHeight // add initial height for chars + end margin
|
val nextSizeY = nextY - initialOffset.y + renderInfo.charHeight // add initial height for chars + end margin
|
||||||
if (nextSizeY > elementMaxSize.y) {
|
if (nextSizeY > elementMaxSize.y) {
|
||||||
@ -97,7 +96,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addX(width: Int, wrap: Boolean = true): Boolean {
|
fun addX(width: Float, wrap: Boolean = true): Boolean {
|
||||||
val nextX = offset.x + width
|
val nextX = offset.x + width
|
||||||
val nextSizeX = nextX - initialOffset.x - renderInfo.charMargin // end margin
|
val nextSizeX = nextX - initialOffset.x - renderInfo.charMargin // end margin
|
||||||
if (nextSizeX > elementMaxSize.x) {
|
if (nextSizeX > elementMaxSize.x) {
|
||||||
@ -121,7 +120,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (size.y == 0) {
|
if (size.y == 0.0f) {
|
||||||
// Add initial height of the letter for the first line
|
// Add initial height of the letter for the first line
|
||||||
val nextSizeY = renderInfo.charHeight
|
val nextSizeY = renderInfo.charHeight
|
||||||
if (nextSizeY > elementMaxSize.y) {
|
if (nextSizeY > elementMaxSize.y) {
|
||||||
@ -147,7 +146,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val charData = context.font[char] ?: continue
|
val charData = font?.get(char) ?: context.font.default[char] ?: continue
|
||||||
|
|
||||||
val charWidth = charData.calculateWidth(renderInfo.scale, renderInfo.shadow)
|
val charWidth = charData.calculateWidth(renderInfo.scale, renderInfo.shadow)
|
||||||
var width = charWidth
|
var width = charWidth
|
||||||
@ -168,7 +167,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
val letterOffset = Vec2i(offset.x + alignmentXOffset, offset.y)
|
val letterOffset = Vec2(offset.x + alignmentXOffset, offset.y)
|
||||||
|
|
||||||
// remove width from the offset again
|
// remove width from the offset again
|
||||||
letterOffset.x -= charWidth
|
letterOffset.x -= charWidth
|
||||||
@ -178,7 +177,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
// ToDo: Remove Font.HORIZONTAL_SPACING
|
// ToDo: Remove Font.HORIZONTAL_SPACING
|
||||||
}
|
}
|
||||||
|
|
||||||
consumer?.let { charData.render(letterOffset, color, shadow, italic, bold, strikethrough, underlined, it, options, renderInfo.scale) }
|
consumer?.let { charData.render(letterOffset, color, shadow, text.formatting, it, options, renderInfo.scale) }
|
||||||
|
|
||||||
if (consumer == null) {
|
if (consumer == null) {
|
||||||
currentLineText += char.toChar()
|
currentLineText += char.toChar()
|
||||||
@ -207,18 +206,16 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
|||||||
|
|
||||||
override fun render3dFlat(context: RenderContext, offset: Vec2i, scale: Float, maxSize: Vec2i, consumer: WorldGUIConsumer, text: TextComponent, light: Int) {
|
override fun render3dFlat(context: RenderContext, offset: Vec2i, scale: Float, maxSize: Vec2i, consumer: WorldGUIConsumer, text: TextComponent, light: Int) {
|
||||||
val color = text.color ?: ChatColors.BLACK
|
val color = text.color ?: ChatColors.BLACK
|
||||||
val italic = text.formatting.contains(FormattingCodes.ITALIC)
|
|
||||||
val bold = text.formatting.contains(FormattingCodes.BOLD)
|
val font = context.font[text.font]
|
||||||
val strikethrough = text.formatting.contains(FormattingCodes.STRIKETHROUGH)
|
|
||||||
val underlined = text.formatting.contains(FormattingCodes.UNDERLINED)
|
|
||||||
|
|
||||||
for (char in text.message.codePoints()) {
|
for (char in text.message.codePoints()) {
|
||||||
val data = context.font[char] ?: continue
|
val data = font?.get(char) ?: context.font.default[char] ?: continue
|
||||||
val expectedWidth = ((data.width + 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, italic = italic, bold = bold, strikethrough = strikethrough, underlined = underlined, scale = scale) + Font.HORIZONTAL_SPACING) * scale).toInt()
|
val width = ((data.render3d(consumer, color, shadow = false, text.formatting, scale = scale) + 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()))
|
||||||
}
|
}
|
||||||
|
@ -17,5 +17,5 @@ import de.bixilon.minosoft.data.text.BaseComponent
|
|||||||
|
|
||||||
data class TextLineInfo(
|
data class TextLineInfo(
|
||||||
val text: BaseComponent = BaseComponent(),
|
val text: BaseComponent = BaseComponent(),
|
||||||
var width: Int = 0,
|
var width: Float = 0.0f,
|
||||||
)
|
)
|
||||||
|
@ -21,7 +21,7 @@ import de.bixilon.minosoft.util.logging.LogMessageType
|
|||||||
|
|
||||||
class TextRenderInfo(
|
class TextRenderInfo(
|
||||||
val fontAlignment: HorizontalAlignments,
|
val fontAlignment: HorizontalAlignments,
|
||||||
val charHeight: Int,
|
val charHeight: Float,
|
||||||
val charMargin: Int,
|
val charMargin: Int,
|
||||||
val scale: Float,
|
val scale: Float,
|
||||||
val shadow: Boolean,
|
val shadow: Boolean,
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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.properties
|
||||||
|
|
||||||
|
object FontProperties {
|
||||||
|
const val MAX_CHAR_WIDTH = 16 // maximum width that a char can have
|
||||||
|
const val CHAR_BASE_HEIGHT = 8 // base height of every char, it is allowed to take up the spacing if needed
|
||||||
|
const val CHAR_SPACING_TOP = 1
|
||||||
|
const val CHAR_SPACING_BOTTOM = 2 // larger to not break underlined text
|
||||||
|
|
||||||
|
const val LINE_HEIGHT = CHAR_SPACING_TOP + CHAR_BASE_HEIGHT + CHAR_SPACING_BOTTOM
|
||||||
|
}
|
@ -11,10 +11,13 @@
|
|||||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.font.renderer
|
package de.bixilon.minosoft.gui.rendering.font.renderer.properties
|
||||||
|
|
||||||
object FontProperties {
|
object FormattingProperties {
|
||||||
const val MAX_CHAR_WIDTH = 16 // maximum width that a char can have
|
const val ITALIC_OFFSET = 2.5f
|
||||||
const val CHAR_HEIGHT = 12 // height every char has
|
const val SHADOW_OFFSET = 1.0f
|
||||||
const val CHAR_SPACING = 1 // spacing every char has around itself
|
const val BOLD_OFFSET = 0.5f
|
||||||
|
|
||||||
|
|
||||||
|
const val SHADOW_COLOR = 0.25f
|
||||||
}
|
}
|
@ -14,16 +14,20 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.font.types.bitmap
|
package de.bixilon.minosoft.gui.rendering.font.types.bitmap
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.code.CodePointRenderer
|
import de.bixilon.minosoft.gui.rendering.font.renderer.code.AscentedCodePointRenderer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.font.renderer.code.RasterizedCodePointRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||||
|
|
||||||
class BitmapCodeRenderer(
|
class BitmapCodeRenderer(
|
||||||
val texture: AbstractTexture,
|
override val texture: AbstractTexture,
|
||||||
var uvStart: Vec2,
|
override var uvStart: Vec2,
|
||||||
var uvEnd: Vec2,
|
override var uvEnd: Vec2,
|
||||||
val width: Float,
|
override val width: Float,
|
||||||
) : CodePointRenderer {
|
) : RasterizedCodePointRenderer, AscentedCodePointRenderer {
|
||||||
|
override val ascent: Float
|
||||||
|
get() = 1.0f
|
||||||
|
override val descent: Float
|
||||||
|
get() = 1.0f
|
||||||
|
|
||||||
fun updateArray() {
|
fun updateArray() {
|
||||||
uvStart = uvStart * texture.textureArrayUV
|
uvStart = uvStart * texture.textureArrayUV
|
||||||
|
@ -16,8 +16,8 @@ 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.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.FontProperties.MAX_CHAR_WIDTH
|
|
||||||
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.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
|
||||||
|
|
||||||
@ -31,5 +31,5 @@ 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, formatting: TextFormatting, consumer: GUIVertexConsumer, options: GUIVertexOptions?, scale: Float) = Unit
|
override fun render(position: Vec2, color: RGBColor, shadow: Boolean, formatting: TextFormatting, consumer: GUIVertexConsumer, options: GUIVertexOptions?, scale: Float) = Unit
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ class EmptyFontType(
|
|||||||
fun load(data: JsonObject): Int2ObjectOpenHashMap<EmptyCodeRenderer>? {
|
fun load(data: JsonObject): Int2ObjectOpenHashMap<EmptyCodeRenderer>? {
|
||||||
val advances = data["advances"]?.toJsonObject() ?: return null
|
val advances = data["advances"]?.toJsonObject() ?: return null
|
||||||
|
|
||||||
val spaces = Int2ObjectOpenHashMap<EmptyCodeRenderer>(advances.size, 0.0f)
|
val spaces = Int2ObjectOpenHashMap<EmptyCodeRenderer>(advances.size, 0.01f)
|
||||||
for ((char, spacing) in advances) {
|
for ((char, spacing) in advances) {
|
||||||
val codePoint = char.codePointAt(0)
|
val codePoint = char.codePointAt(0)
|
||||||
|
|
||||||
|
@ -14,15 +14,15 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.font.types.unicode.legacy
|
package de.bixilon.minosoft.gui.rendering.font.types.unicode.legacy
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.code.CodePointRenderer
|
import de.bixilon.minosoft.gui.rendering.font.renderer.code.RasterizedCodePointRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||||
|
|
||||||
class LegacyUnicodeCodeRenderer(
|
class LegacyUnicodeCodeRenderer(
|
||||||
val texture: AbstractTexture,
|
override val texture: AbstractTexture,
|
||||||
var uvStart: Vec2,
|
override var uvStart: Vec2,
|
||||||
var uvEnd: Vec2,
|
override var uvEnd: Vec2,
|
||||||
val width: Float,
|
override val width: Float,
|
||||||
) : CodePointRenderer {
|
) : RasterizedCodePointRenderer {
|
||||||
|
|
||||||
|
|
||||||
fun updateArray() {
|
fun updateArray() {
|
||||||
|
@ -21,8 +21,8 @@ import de.bixilon.minosoft.assets.AssetsManager
|
|||||||
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
|
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
|
||||||
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.FontProperties
|
import de.bixilon.minosoft.gui.rendering.font.renderer.properties.FontProperties
|
||||||
import de.bixilon.minosoft.gui.rendering.font.types.FontType
|
import de.bixilon.minosoft.gui.rendering.font.types.PostInitFontType
|
||||||
import de.bixilon.minosoft.gui.rendering.font.types.factory.FontTypeFactory
|
import de.bixilon.minosoft.gui.rendering.font.types.factory.FontTypeFactory
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.StaticTextureArray
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.StaticTextureArray
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
|
||||||
@ -32,7 +32,7 @@ import java.io.InputStream
|
|||||||
|
|
||||||
class LegacyUnicodeFontType(
|
class LegacyUnicodeFontType(
|
||||||
val chars: Array<LegacyUnicodeCodeRenderer?>,
|
val chars: Array<LegacyUnicodeCodeRenderer?>,
|
||||||
) : FontType {
|
) : PostInitFontType {
|
||||||
|
|
||||||
override fun postInit(latch: AbstractLatch) {
|
override fun postInit(latch: AbstractLatch) {
|
||||||
for (char in chars) {
|
for (char in chars) {
|
||||||
@ -51,7 +51,7 @@ class LegacyUnicodeFontType(
|
|||||||
private const val CHAR_ROW = 0x0F
|
private const val CHAR_ROW = 0x0F
|
||||||
private const val CHAR_SIZE = 0x0F
|
private const val CHAR_SIZE = 0x0F
|
||||||
private const val PIXEL = 1.0f / (CHAR_SIZE * CHAR_ROW)
|
private const val PIXEL = 1.0f / (CHAR_SIZE * CHAR_ROW)
|
||||||
private const val WIDTH_SCALE = FontProperties.CHAR_HEIGHT / CHAR_SIZE.toFloat()
|
private const val WIDTH_SCALE = FontProperties.CHAR_BASE_HEIGHT / CHAR_SIZE.toFloat()
|
||||||
|
|
||||||
override fun build(context: RenderContext, data: Map<String, Any>): LegacyUnicodeFontType? {
|
override fun build(context: RenderContext, data: Map<String, Any>): LegacyUnicodeFontType? {
|
||||||
val assets = context.connection.assetsManager
|
val assets = context.connection.assetsManager
|
||||||
|
@ -67,7 +67,7 @@ abstract class Element(val guiRenderer: GUIRenderer, initialCacheSize: Int = 100
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Warning: Should not be directly accessed!")
|
@Deprecated("Warning: Should not be directly accessed!")
|
||||||
open val cache = GUIMeshCache(guiRenderer.halfSize, context.renderSystem.primitiveMeshOrder, initialCacheSize)
|
open val cache = GUIMeshCache(guiRenderer.halfSize, context.renderSystem.primitiveMeshOrder, context, initialCacheSize)
|
||||||
|
|
||||||
private var previousMaxSize = Vec2i.EMPTY
|
private var previousMaxSize = Vec2i.EMPTY
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.gui.elements
|
package de.bixilon.minosoft.gui.rendering.gui.elements
|
||||||
|
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
|
|
||||||
enum class HorizontalAlignments {
|
enum class HorizontalAlignments {
|
||||||
@ -22,6 +23,14 @@ enum class HorizontalAlignments {
|
|||||||
;
|
;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
fun HorizontalAlignments.getOffset(width: Float, childWidth: Float): Float {
|
||||||
|
return when (this) {
|
||||||
|
LEFT -> 0.0f
|
||||||
|
RIGHT -> width - childWidth
|
||||||
|
CENTER -> (width - childWidth) / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun HorizontalAlignments.getOffset(width: Int, childWidth: Int): Int {
|
fun HorizontalAlignments.getOffset(width: Int, childWidth: Int): Int {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
LEFT -> 0
|
LEFT -> 0
|
||||||
@ -33,5 +42,9 @@ enum class HorizontalAlignments {
|
|||||||
fun HorizontalAlignments.getOffset(size: Vec2i, childSize: Vec2i): Vec2i {
|
fun HorizontalAlignments.getOffset(size: Vec2i, childSize: Vec2i): Vec2i {
|
||||||
return Vec2i(getOffset(size.x, childSize.x), 0)
|
return Vec2i(getOffset(size.x, childSize.x), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun HorizontalAlignments.getOffset(size: Vec2, childSize: Vec2): Vec2 {
|
||||||
|
return Vec2(getOffset(size.x, childSize.x), 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.gui.elements.text
|
package de.bixilon.minosoft.gui.rendering.gui.elements.text
|
||||||
|
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2i
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
import de.bixilon.kutil.cast.CastUtil.unsafeNull
|
import de.bixilon.kutil.cast.CastUtil.unsafeNull
|
||||||
import de.bixilon.kutil.primitive.BooleanUtil.decide
|
import de.bixilon.kutil.primitive.BooleanUtil.decide
|
||||||
@ -36,6 +37,7 @@ 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
|
||||||
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.window.CursorShapes
|
import de.bixilon.minosoft.gui.rendering.system.window.CursorShapes
|
||||||
|
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2Util.EMPTY
|
||||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
||||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec4.Vec4iUtil.offset
|
import de.bixilon.minosoft.gui.rendering.util.vec.vec4.Vec4iUtil.offset
|
||||||
import de.bixilon.minosoft.util.KUtil.charCount
|
import de.bixilon.minosoft.util.KUtil.charCount
|
||||||
@ -118,12 +120,12 @@ open class TextElement(
|
|||||||
if (!emptyMessage) {
|
if (!emptyMessage) {
|
||||||
val renderInfo = TextRenderInfo(
|
val renderInfo = TextRenderInfo(
|
||||||
fontAlignment = fontAlignment,
|
fontAlignment = fontAlignment,
|
||||||
charHeight = charHeight,
|
charHeight = charHeight.toFloat(),
|
||||||
charMargin = charMargin,
|
charMargin = charMargin,
|
||||||
scale = scale,
|
scale = scale,
|
||||||
shadow = shadow,
|
shadow = shadow,
|
||||||
)
|
)
|
||||||
ChatComponentRenderer.render(Vec2i.EMPTY, Vec2i.EMPTY, prefSize, InfiniteSizeElement(guiRenderer), context, null, null, renderInfo, value)
|
ChatComponentRenderer.render(Vec2.EMPTY, Vec2.EMPTY, Vec2(prefSize), InfiniteSizeElement(guiRenderer), context, null, null, renderInfo, value)
|
||||||
}
|
}
|
||||||
_prefSize = prefSize
|
_prefSize = prefSize
|
||||||
}
|
}
|
||||||
@ -151,13 +153,13 @@ open class TextElement(
|
|||||||
val size = Vec2i.EMPTY
|
val size = Vec2i.EMPTY
|
||||||
val renderInfo = TextRenderInfo(
|
val renderInfo = TextRenderInfo(
|
||||||
fontAlignment = fontAlignment,
|
fontAlignment = fontAlignment,
|
||||||
charHeight = charHeight,
|
charHeight = charHeight.toFloat(),
|
||||||
charMargin = charMargin,
|
charMargin = charMargin,
|
||||||
scale = scale,
|
scale = scale,
|
||||||
shadow = shadow,
|
shadow = shadow,
|
||||||
)
|
)
|
||||||
if (!emptyMessage) {
|
if (!emptyMessage) {
|
||||||
ChatComponentRenderer.render(Vec2i.EMPTY, Vec2i.EMPTY, size, this, context, null, null, renderInfo, chatComponent)
|
ChatComponentRenderer.render(Vec2.EMPTY, Vec2.EMPTY, Vec2(size), this, context, null, null, renderInfo, chatComponent)
|
||||||
renderInfo.lineIndex = 0
|
renderInfo.lineIndex = 0
|
||||||
}
|
}
|
||||||
if (renderInfo.lines.size > 1 && size.y > Font.CHAR_HEIGHT) {
|
if (renderInfo.lines.size > 1 && size.y > Font.CHAR_HEIGHT) {
|
||||||
@ -180,7 +182,7 @@ open class TextElement(
|
|||||||
|
|
||||||
if (background) {
|
if (background) {
|
||||||
for ((line, info) in renderInfo.lines.withIndex()) {
|
for ((line, info) in renderInfo.lines.withIndex()) {
|
||||||
val start = initialOffset + Vec2i(fontAlignment.getOffset(size.x, info.width), line * charHeight)
|
val start = initialOffset + Vec2i(fontAlignment.getOffset(size.x.toFloat(), info.width), line * charHeight)
|
||||||
consumer.addQuad(start, start + Vec2i(info.width + charMargin, charHeight), context.textureManager.whiteTexture, backgroundColor, options)
|
consumer.addQuad(start, start + Vec2i(info.width + charMargin, charHeight), context.textureManager.whiteTexture, backgroundColor, options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,7 +192,7 @@ open class TextElement(
|
|||||||
vertices *= 2
|
vertices *= 2
|
||||||
}
|
}
|
||||||
consumer.ensureSize(vertices)
|
consumer.ensureSize(vertices)
|
||||||
ChatComponentRenderer.render(initialOffset, Vec2i(initialOffset), Vec2i.EMPTY, this, context, consumer, options, renderInfo, chatComponent)
|
ChatComponentRenderer.render(Vec2(initialOffset), Vec2(initialOffset), Vec2.EMPTY, this, context, consumer, options, renderInfo, chatComponent)
|
||||||
renderInfo.lineIndex = 0
|
renderInfo.lineIndex = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,10 +264,10 @@ open class TextElement(
|
|||||||
charToCheck++
|
charToCheck++
|
||||||
}
|
}
|
||||||
val text = line.text.getTextAt(charToCheck)
|
val text = line.text.getTextAt(charToCheck)
|
||||||
offset.x -= line0.width // ToDo: Not 100% correct
|
offset.x -= line0.width.toInt() // ToDo: Not 100% correct
|
||||||
|
|
||||||
|
|
||||||
offset.x += fontAlignment.getOffset(size.x, line.width)
|
offset.x += fontAlignment.getOffset(size.x, line.width.toInt())
|
||||||
return Pair(text, offset)
|
return Pair(text, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ class MarkTextElement(
|
|||||||
val preMark = TextElement(guiRenderer, message.substring(0, markStartPosition), scale = scale, parent = _parent)
|
val preMark = TextElement(guiRenderer, message.substring(0, markStartPosition), scale = scale, parent = _parent)
|
||||||
val mark = TextElement(guiRenderer, message.substring(markStartPosition, markEndPosition), scale = scale, parent = _parent)
|
val mark = TextElement(guiRenderer, message.substring(markStartPosition, markEndPosition), scale = scale, parent = _parent)
|
||||||
val markOffset = Vec2i(preMark.renderInfo.lines.lastOrNull()?.width ?: 0, preMark.size.y)
|
val markOffset = Vec2i(preMark.renderInfo.lines.lastOrNull()?.width ?: 0, preMark.size.y)
|
||||||
if (markOffset.y > 0 && (preMark.renderInfo.lines.lastOrNull()?.width ?: 0) <= (renderInfo.lines.lastOrNull()?.width ?: 0)) {
|
if (markOffset.y > 0 && (preMark.renderInfo.lines.lastOrNull()?.width ?: 0.0f) <= (renderInfo.lines.lastOrNull()?.width ?: 0.0f)) {
|
||||||
markOffset.y -= (Font.TOTAL_CHAR_HEIGHT * scale).toInt()
|
markOffset.y -= (Font.TOTAL_CHAR_HEIGHT * scale).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,8 +344,8 @@ open class TextInputElement(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val charDelta = position.x - line.width
|
val charDelta = position.x - line.width
|
||||||
val width = guiRenderer.context.font[value.codePointAtOrNull(pointer) ?: break]?.width ?: break
|
val width = guiRenderer.context.font.default[value.codePointAtOrNull(pointer) ?: break]?.calculateWidth(1.0f, true) ?: break
|
||||||
if (charDelta != 0 && charDelta >= width / 2) {
|
if (charDelta != 0.0f && charDelta >= width / 2) {
|
||||||
pointer++
|
pointer++
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
@ -18,12 +18,14 @@ import de.bixilon.kotlinglm.vec2.Vec2i
|
|||||||
import de.bixilon.kutil.collections.primitive.floats.AbstractFloatList
|
import de.bixilon.kutil.collections.primitive.floats.AbstractFloatList
|
||||||
import de.bixilon.kutil.collections.primitive.floats.HeapArrayFloatList
|
import de.bixilon.kutil.collections.primitive.floats.HeapArrayFloatList
|
||||||
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.system.base.texture.ShaderIdentifiable
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.ShaderIdentifiable
|
||||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
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,
|
||||||
initialCacheSize: Int = 1000,
|
initialCacheSize: Int = 1000,
|
||||||
var data: AbstractFloatList = HeapArrayFloatList(initialCacheSize),
|
var data: AbstractFloatList = HeapArrayFloatList(initialCacheSize),
|
||||||
) : GUIVertexConsumer {
|
) : GUIVertexConsumer {
|
||||||
|
@ -16,10 +16,12 @@ 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.gui.atlas.TextureLike
|
import de.bixilon.minosoft.gui.rendering.gui.atlas.TextureLike
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.ShaderIdentifiable
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.ShaderIdentifiable
|
||||||
|
|
||||||
interface GUIVertexConsumer {
|
interface GUIVertexConsumer {
|
||||||
|
val context: RenderContext
|
||||||
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?)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user