hud: font rendering fixes, more debug info

This commit is contained in:
Bixilon 2021-09-11 11:35:42 +02:00
parent 034e6e8f01
commit 39758cf057
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
11 changed files with 119 additions and 56 deletions

View File

@ -38,6 +38,7 @@ class Font(
const val CHAR_MARGIN = 1 // used for background
const val TOTAL_CHAR_HEIGHT = CHAR_HEIGHT + 2 * CHAR_MARGIN // top and bottom
const val HORIZONTAL_SPACING = 1
const val HORIZONTAL_SPACING_SHADOW = 0
const val VERTICAL_SPACING = 3
}
}

View File

@ -22,21 +22,35 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.Element
import de.bixilon.minosoft.gui.rendering.gui.elements.ElementAlignments
import de.bixilon.minosoft.gui.rendering.gui.elements.ElementAlignments.Companion.getOffset
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
import de.bixilon.minosoft.util.KUtil.decide
import de.bixilon.minosoft.util.MMath.ceil
import glm_.vec2.Vec2i
object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
override fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, z: Int, element: Element, fontAlignment: ElementAlignments, renderWindow: RenderWindow, consumer: GUIVertexConsumer?, renderInfo: TextRenderInfo, text: TextComponent): Boolean {
if (text.message.isEmpty()) {
return false
}
val elementMaxSize = element.maxSize
val shadow = text.formatting.contains(PreChatFormattingCodes.SHADOWED)
// ToDo: Only 1 quad for the underline and the strikethrough
var alignmentXOffset = 0
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
return true
}
fun applyOffset() {
if (consumer == null) {
// preparing phase
renderInfo.lines += TextLineInfo()
} else {
alignmentXOffset = fontAlignment.getOffset(element.size.x, renderInfo.currentLine.width)
}
}
fun addY(height: Int): Boolean {
val nextY = offset.y + height
val nextSizeY = nextY - initialOffset.y + Font.TOTAL_CHAR_HEIGHT // add initial height for chars + end margin
@ -54,14 +68,9 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
if (addY(Font.TOTAL_CHAR_HEIGHT)) {
return true
}
renderInfo.currentLine++
renderInfo.currentLineNumber++
offset.x = initialOffset.x + Font.CHAR_MARGIN
if (consumer == null) {
// preparing phase
renderInfo.lines += TextLineInfo()
} else {
alignmentXOffset = fontAlignment.getOffset(element.size.x, renderInfo.lines[renderInfo.currentLine].width)
}
applyOffset()
return false
}
@ -78,7 +87,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
return addX(width, false)
}
if (consumer == null) {
renderInfo.lines[renderInfo.currentLine].width += width
renderInfo.currentLine.width += width
}
offset.x = nextX
if (nextSizeX > size.x) {
@ -94,15 +103,11 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
if (nextSizeY > elementMaxSize.y) {
return true
}
if (consumer != null) {
alignmentXOffset = fontAlignment.getOffset(element.size.x, renderInfo.lines[renderInfo.currentLine].width)
} else {
renderInfo.lines += TextLineInfo() // add line 0
}
size.y = nextSizeY
size.x += Font.CHAR_MARGIN * 2
offset += Font.CHAR_MARGIN
}
applyOffset()
for (charCode in text.message.codePoints().toArray()) {
@ -126,7 +131,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
if (offset.x != initialOffset.x + Font.CHAR_MARGIN) {
// add spacing between letters
width += Font.HORIZONTAL_SPACING
width += shadow.decide(Font.HORIZONTAL_SPACING_SHADOW, Font.HORIZONTAL_SPACING)
}
val previousY = offset.y
@ -147,7 +152,7 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
consumer?.let { charData.render(letterOffset, z, text, it) }
if (consumer == null) {
renderInfo.lines[renderInfo.currentLine].chars += char
renderInfo.currentLine.chars += char
}
}

View File

@ -15,5 +15,8 @@ package de.bixilon.minosoft.gui.rendering.font.renderer
class TextRenderInfo(
val lines: MutableList<TextLineInfo> = mutableListOf(),
var currentLine: Int = 0,
)
var currentLineNumber: Int = 0,
) {
val currentLine: TextLineInfo
get() = lines[currentLineNumber]
}

View File

@ -13,13 +13,15 @@
package de.bixilon.minosoft.gui.rendering.gui.elements.text
import de.bixilon.minosoft.gui.rendering.gui.elements.ElementAlignments
import de.bixilon.minosoft.gui.rendering.gui.hud.HUDRenderer
class AutoTextElement(
hudRenderer: HUDRenderer,
var interval: Int,
alignment: ElementAlignments = ElementAlignments.LEFT,
private val updater: () -> Any,
) : TextElement(hudRenderer, "") {
) : TextElement(hudRenderer, "", alignment) {
private var remainingTicks = 0
init {

View File

@ -46,11 +46,16 @@ open class TextElement(
prepared = false
}
private var emptyMessage: Boolean = true
final override var textComponent: ChatComponent = ChatComponent.of("")
protected set(value) {
field = value
emptyMessage = value.message.isEmpty()
val prefSize = Vec2i.EMPTY
ChatComponentRenderer.render(Vec2i.EMPTY, Vec2i.EMPTY, prefSize, 0, InfiniteSizeElement(hudRenderer), fontAlignment, renderWindow, null, TextRenderInfo(), value)
if (!emptyMessage) {
ChatComponentRenderer.render(Vec2i.EMPTY, Vec2i.EMPTY, prefSize, 0, InfiniteSizeElement(hudRenderer), fontAlignment, renderWindow, null, TextRenderInfo(), value)
}
this.prefSize = prefSize
apply()
}
@ -62,17 +67,16 @@ open class TextElement(
}
override fun silentApply() {
size = Vec2i.EMPTY
if (textComponent.message.isNotEmpty()) {
val size = Vec2i.EMPTY
val size = Vec2i.EMPTY
if (!emptyMessage) {
val renderInfo = TextRenderInfo()
ChatComponentRenderer.render(Vec2i.EMPTY, Vec2i.EMPTY, size, 0, this, fontAlignment, renderWindow, null, renderInfo, textComponent)
renderInfo.currentLine = 0
renderInfo.currentLineNumber = 0
this.renderInfo = renderInfo
this.size = size
preparedSize = size
}
this.size = size
preparedSize = size
}
override fun apply() {
@ -96,10 +100,13 @@ open class TextElement(
override fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer): Int {
if (emptyMessage) {
return 0
}
val initialOffset = offset + margin.offset
ChatComponentRenderer.render(initialOffset, Vec2i(initialOffset), Vec2i.EMPTY, z + 1, this, fontAlignment, renderWindow, consumer, renderInfo, textComponent)
renderInfo.currentLine = 0
renderInfo.currentLineNumber = 0
prepared = true
if (background) {

View File

@ -63,7 +63,7 @@ class DebugHUD(val hudRenderer: HUDRenderer) : HUD<GridLayout> {
private fun initLeft(): Element {
val layout = RowLayout(hudRenderer)
layout.margin = Vec4i(5)
layout.margin = Vec4i(2)
layout += TextElement(hudRenderer, TextComponent(RunConfiguration.VERSION_STRING, ChatColors.RED))
layout += AutoTextElement(hudRenderer, 1) { "FPS ${renderWindow.renderStats.smoothAvgFPS.round10}" }
renderWindow[WorldRenderer]?.apply {
@ -93,7 +93,7 @@ class DebugHUD(val hudRenderer: HUDRenderer) : HUD<GridLayout> {
layout += LineSpacerElement(hudRenderer)
layout += TextElement(hudRenderer, "Difficulty ${connection.world.difficulty.format()}, ${connection.world.difficultyLocked.decide("locked", "unlocked")}", ElementAlignments.RIGHT).apply {
layout += TextElement(hudRenderer, "Difficulty ${connection.world.difficulty.format()}, ${connection.world.difficultyLocked.decide("locked", "unlocked")}").apply {
connection.registerEvent(CallbackEventInvoker.of<DifficultyChangeEvent> {
text = "Difficulty ${it.difficulty.format()}, ${it.locked.decide("locked", "unlocked")}"
})
@ -104,7 +104,7 @@ class DebugHUD(val hudRenderer: HUDRenderer) : HUD<GridLayout> {
private fun initRight(): Element {
val layout = RowLayout(hudRenderer, ElementAlignments.RIGHT)
layout.margin = Vec4i(5)
layout.margin = Vec4i(2)
layout += TextElement(hudRenderer, "Java ${Runtime.version()} ${System.getProperty("sun.arch.data.model")}bit", ElementAlignments.RIGHT)
layout += LineSpacerElement(hudRenderer)
@ -137,6 +137,14 @@ class DebugHUD(val hudRenderer: HUDRenderer) : HUD<GridLayout> {
layout += TextElement(hudRenderer, "Mods ${ModLoader.MOD_MAP.size}x loaded, ${connection.size}x listeners", ElementAlignments.RIGHT)
layout += LineSpacerElement(hudRenderer)
renderWindow.inputHandler.camera.apply {
layout += AutoTextElement(hudRenderer, 1, ElementAlignments.RIGHT) {
// ToDo: Tags
target ?: return@AutoTextElement ""
}
}
return layout
}
}

View File

@ -69,6 +69,7 @@ class Camera(
var cameraRight = Vec3d(0.0, 0.0, -1.0)
private var cameraUp = Vec3d(0.0, 1.0, 0.0)
// ToDo: They should also be available in headless mode
var target: RaycastHit? = null
private set
var blockTarget: BlockRaycastHit? = null // Block target or if blocked by entity null

View File

@ -15,7 +15,9 @@ package de.bixilon.minosoft.gui.rendering.input.camera.hit
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.registries.blocks.BlockState
import de.bixilon.minosoft.util.KUtil.format
import de.bixilon.minosoft.data.text.BaseComponent
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.TextFormattable
import glm_.vec3.Vec3d
import glm_.vec3.Vec3i
@ -25,23 +27,29 @@ open class BlockRaycastHit(
hitDirection: Directions,
val blockState: BlockState,
val blockPosition: Vec3i,
) : RaycastHit(position, distance, hitDirection) {
) : RaycastHit(position, distance, hitDirection), TextFormattable {
val hitPosition = position - blockPosition
override fun toString(): String {
val ret = StringBuilder()
ret.append(blockPosition)
ret.append(": ")
ret.append(blockState.block.resourceLocation)
return toText().legacyText
}
for ((key, value) in blockState.properties) {
ret.append('\n')
ret.append(' ')
ret.append(key.group)
ret.append(": ")
ret.append(value.format())
override fun toText(): ChatComponent {
val text = BaseComponent()
text += "Block target "
text += blockPosition
text += ": "
text += blockState.block.resourceLocation
for ((property, value) in blockState.properties) {
text += "\n"
text += property
text += ": "
text += value
}
return ret.toString()
return text
}
}

View File

@ -34,20 +34,25 @@ class EntityRaycastHit(
override fun toText(): ChatComponent {
val text = BaseComponent()
text += "Entity target "
text += position
text += (": ")
text += ": "
text += entity.entityType.resourceLocation
text += "\n Id: "
text += entity.id
text += "\n UUID: "
text += entity.uuid
text += "\n"
text += "Id: ${entity.id}"
text += "\n"
text += "UUID: ${entity.uuid}"
for ((key, value) in entity.entityMetaDataFormatted) {
text += "\n "
text += key
val metaData = entity.entityMetaDataFormatted
if (metaData.isNotEmpty()) {
text += "\n"
}
for ((property, value) in metaData) {
text += "\n"
text += property
text += ": "
text += value
}

View File

@ -15,8 +15,10 @@ package de.bixilon.minosoft.gui.rendering.input.camera.hit
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.registries.blocks.BlockState
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
import de.bixilon.minosoft.data.registries.fluid.Fluid
import de.bixilon.minosoft.data.text.BaseComponent
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.TextFormattable
import glm_.vec3.Vec3d
import glm_.vec3.Vec3i
@ -27,9 +29,27 @@ class FluidRaycastHit(
val blockState: BlockState,
val blockPosition: Vec3i,
val fluid: Fluid,
) : RaycastHit(position, distance, hitDirection) {
) : RaycastHit(position, distance, hitDirection), TextFormattable {
override fun toString(): String {
return "$blockPosition: ${fluid.resourceLocation}\n Height: ${fluid.getHeight(blockState)}\n Level: ${blockState.properties[BlockProperties.FLUID_LEVEL]}"
return toText().legacyText
}
override fun toText(): ChatComponent {
val text = BaseComponent()
text += "Fluid target "
text += blockPosition
text += ": "
text += fluid.resourceLocation
for ((property, value) in blockState.properties) {
text += "\n"
text += property
text += ": "
text += value
}
return text
}
}

View File

@ -29,6 +29,7 @@ import de.bixilon.minosoft.util.enum.AliasableEnum
import de.bixilon.minosoft.util.json.JSONSerializer
import glm_.vec2.Vec2t
import glm_.vec3.Vec3t
import glm_.vec4.Vec4t
import okio.Buffer
import sun.misc.Unsafe
import java.io.PrintWriter
@ -255,6 +256,8 @@ object KUtil {
is Float -> "§d%.3f".format(this)
is Double -> "§d%.4f".format(this)
is Number -> TextComponent(this).color(ChatColors.LIGHT_PURPLE)
is ResourceLocation -> TextComponent(this.toString()).color(ChatColors.GOLD)
is Vec4t<*> -> "(${this.x.format()} ${this.y.format()} ${this.z.format()} ${this.w.format()})"
is Vec3t<*> -> "(${this.x.format()} ${this.y.format()} ${this.z.format()})"
is Vec2t<*> -> "(${this.x.format()} ${this.y.format()})"
else -> this.toString()