diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/position/HUDElementVec2.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/position/HUDElementVec2.kt
index db7fb6bd6..d60fc0dc6 100644
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/position/HUDElementVec2.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/position/HUDElementVec2.kt
@@ -2,6 +2,7 @@ package de.bixilon.minosoft.gui.rendering.hud.elements.position
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
+import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
@@ -25,9 +26,11 @@ class HUDElementVec2(
}
companion object {
+ private val ZERO_VECTOR = HUDElementVec2(Vec2.EMPTY, HUDElementPositionUnits.PIXELS)
+
fun deserialize(data: Any?): HUDElementVec2? {
if (data !is Map<*, *>) {
- return null
+ return ZERO_VECTOR
}
val xString = data["x"] as String
val yString = data["y"] as String
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HUDElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HUDElement.kt
index 2fbf101b6..eec359f88 100644
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HUDElement.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HUDElement.kt
@@ -18,9 +18,10 @@ import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.elements.position.HUDElementPositionAnchors
import de.bixilon.minosoft.gui.rendering.hud.elements.position.HUDElementVec2
import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec2
+import de.bixilon.minosoft.gui.rendering.util.mesh.SimpleTextureMesh
import glm_.vec2.Vec2i
-abstract class HUDElement(
+open class HUDElement(
var position: HUDElementPosition,
val size: HUDElementVec2,
val z: Int,
@@ -47,7 +48,7 @@ abstract class HUDElement(
prepareNext = false
}
- fun getPositionAtAnchor(anchor: HUDElementPositionAnchors): Vec2i {
+ open fun getPositionAtAnchor(anchor: HUDElementPositionAnchors): Vec2i {
val realSize = size.getRealVector(hudRenderer).toVec2
val realPosition = position.getRealPosition(hudRenderer)
return realPosition - realSize * position.anchor.positionTransform + realSize * anchor.positionTransform
@@ -76,4 +77,6 @@ abstract class HUDElement(
}
open fun update() {}
+
+ open fun prepare(mesh: SimpleTextureMesh) {}
}
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HUDImageElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HUDImageElement.kt
index 8d7816f90..e3b70e943 100644
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HUDImageElement.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HUDImageElement.kt
@@ -17,7 +17,7 @@ import glm_.vec4.Vec4
import glm_.vec4.swizzle.xy
class HUDImageElement: HUDElement {
- private var mesh = SimpleTextureMesh()
+ private var textureMesh = SimpleTextureMesh()
lateinit var texture: TextureLike
private val textureName: ResourceLocation?
@@ -48,15 +48,10 @@ class HUDImageElement: HUDElement {
}
override fun draw() {
- mesh.draw()
+ textureMesh.draw()
}
- override fun prepare() {
- super.prepare()
- if (mesh.state == Mesh.MeshStates.LOADED) {
- mesh.unload()
- mesh = SimpleTextureMesh()
- }
+ override fun prepare(mesh: SimpleTextureMesh) {
val realZ = RenderConstants.HUD_Z_COORDINATE + RenderConstants.HUD_Z_COORDINATE_Z_FACTOR * z
val positions = position.getPositions(hudRenderer, size.getRealVector(hudRenderer))
val uvs = texture.uvs
@@ -70,7 +65,15 @@ class HUDImageElement: HUDElement {
for (position in DRAW_ORDER) {
addVertex((hudRenderer.orthographicMatrix * Vec4(positions[position], 1f, 1f)).xy, uvs[position])
}
- mesh.load()
+ }
+
+ override fun prepare() {
+ if (textureMesh.state == Mesh.MeshStates.LOADED) {
+ textureMesh.unload()
+ textureMesh = SimpleTextureMesh()
+ }
+ prepare(textureMesh)
+ textureMesh.load()
}
companion object {
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HUDSpacerElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HUDSpacerElement.kt
deleted file mode 100644
index f6d62637c..000000000
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HUDSpacerElement.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Minosoft
- *
- * Copyright (C) 2021 Lukas Eisenhauer
- *
- * 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 .
- *
- * This software is not affiliated with Mojang AB, the original developer of Minecraft.
- */
-
-package de.bixilon.minosoft.gui.rendering.hud.elements.primitive
-
-import de.bixilon.minosoft.gui.rendering.hud.elements.position.HUDElementVec2
-
-class HUDSpacerElement(position: HUDElementPosition, size: HUDElementVec2, z: Int,):
- HUDElement(position, size, z)
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextElement.kt
index 0d074a2d4..1c8545a1a 100644
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextElement.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextElement.kt
@@ -27,18 +27,20 @@ import de.bixilon.minosoft.gui.rendering.hud.elements.position.HUDElementVec2
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.HUDElementPosition
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.HUDImageElement
-import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.HUDSpacerElement
import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec2
+import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
+import de.bixilon.minosoft.gui.rendering.util.mesh.SimpleTextureMesh
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import glm_.glm
import glm_.vec2.Vec2
+import glm_.vec2.Vec2i
class HUDTextElement : HUDElement {
val elements = mutableListOf()
-
+ private var textureMesh = SimpleTextureMesh()
private val alignment: HUDElementPositionAnchors
- private lateinit var contents: List<*>
+ private lateinit var contents: Any
private var currentText: ChatComponent? = null
@@ -46,7 +48,7 @@ class HUDTextElement : HUDElement {
constructor(position: HUDElementPosition, size: HUDElementVec2, json: Map? = null, activeOnMenu: HUDMenus?) : super(position, size, (json?.get("z") as Double?)?.toInt() ?: 0, activeOnMenu) {
alignment = json?.get("alignment")?.let { HUDElementPositionAnchors.of(it as String) } ?: HUDElementPositionAnchors.TOP_LEFT
- contents = json?.get("content") as List<*>
+ contents = json?.get("content")!!
}
constructor(position: HUDElementPosition, size: HUDElementVec2, z: Int) : super(position, size, z) {
@@ -76,8 +78,8 @@ class HUDTextElement : HUDElement {
}
private fun addChars(chars: CharArray, color: RGBColor?, newLinePositions: MutableList): MutableList {
- val maxRight = getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x
- val bottomLeftPosition = getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_LEFT).toVec2
+ val maxRight = super.getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x
+ val bottomLeftPosition = super.getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_LEFT).toVec2
for (char in chars) {
if (char in ProtocolDefinition.LINE_BREAK_CHARS) {
lastElement = null
@@ -88,11 +90,11 @@ class HUDTextElement : HUDElement {
HUDElementPosition(BETWEEN_CHARS_OFFSET, HUDElementPositionAnchors.BOTTOM_LEFT, it, HUDElementPositionAnchors.BOTTOM_RIGHT)
} ?: run {
newLinePositions += elements.size
- HUDElementPosition(HUDElementVec2(getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_LEFT).toVec2, HUDElementPositionUnits.PIXELS), HUDElementPositionAnchors.BOTTOM_LEFT)
+ HUDElementPosition(HUDElementVec2(super.getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_LEFT).toVec2, HUDElementPositionUnits.PIXELS), HUDElementPositionAnchors.BOTTOM_LEFT)
}
val elementSize = HUDElementVec2(fontChar.size.toVec2, HUDElementPositionUnits.SCALED_PIXELS)
val newElement = if (char == ' ') {
- HUDSpacerElement(elementPosition, elementSize, z)
+ HUDElement(elementPosition, elementSize, z)
} else {
HUDImageElement(elementPosition, elementSize, z, fontChar, tint = color)
}
@@ -102,7 +104,7 @@ class HUDTextElement : HUDElement {
lastElement = newElement
if (elementRight > maxRight) {
val relevantIndex = getLastSpacerElementPosition(elements.lastIndex)
- if (elements[relevantIndex] is HUDSpacerElement) {
+ if (elements[relevantIndex] !is HUDImageElement) {
elements.removeAt(relevantIndex)
}
newLinePositions += relevantIndex
@@ -114,11 +116,11 @@ class HUDTextElement : HUDElement {
private fun getLastSpacerElementPosition(position: Int): Int {
for (i in 0..position) {
- val j = position - i - 1
+ val j = glm.max(0, position - i - 1)
if (j == 0) {
return position
}
- if (elements[j] is HUDSpacerElement) {
+ if (elements[j] !is HUDImageElement) {
return j
}
if (elements[j].position.parentElement == null) {
@@ -130,35 +132,43 @@ class HUDTextElement : HUDElement {
private fun adjustPositionsForLineBreaks(newLinePositions: MutableList) {
var y = when (alignment) {
- HUDElementPositionAnchors.TOP_LEFT, HUDElementPositionAnchors.BOTTOM_LEFT -> getPositionAtAnchor(HUDElementPositionAnchors.TOP_LEFT).y
- HUDElementPositionAnchors.TOP_RIGHT, HUDElementPositionAnchors.BOTTOM_RIGHT -> getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).y - (newLinePositions.size - 2) * (Font.CHAR_HEIGHT + 1) * Minosoft.getConfig().config.game.hud.scale.toInt()
+ HUDElementPositionAnchors.TOP_LEFT, HUDElementPositionAnchors.BOTTOM_LEFT -> super.getPositionAtAnchor(HUDElementPositionAnchors.TOP_LEFT).y
+ HUDElementPositionAnchors.TOP_RIGHT, HUDElementPositionAnchors.BOTTOM_RIGHT -> super.getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).y - (newLinePositions.size - 2) * (Font.CHAR_HEIGHT + 1) * Minosoft.getConfig().config.game.hud.scale.toInt()
else -> TODO()
}
- val left = getPositionAtAnchor(HUDElementPositionAnchors.TOP_LEFT).x
- val right = glm.min(hudRenderer.renderWindow.screenDimensions.x, getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x)
+ val left = super.getPositionAtAnchor(HUDElementPositionAnchors.TOP_LEFT).x
+ val right = glm.min(hudRenderer.renderWindow.screenDimensions.x, super.getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x)
for (i in 0 until newLinePositions.lastIndex) {
- elements[newLinePositions[i]].position = alignment.textAlignmentTransform.invoke(left, right, y, elements[newLinePositions[i + 1] - 1])
+ elements[newLinePositions[i]].position = alignment.textAlignmentTransform.invoke(left, right, y, elements[glm.max(0, newLinePositions[i + 1] - 1)])
y += ((Font.CHAR_HEIGHT + 1) * Minosoft.getConfig().config.game.hud.scale).toInt()
}
}
override fun draw() {
- for (element in elements) {
- element.draw()
- }
+ textureMesh.draw()
}
override fun prepare() {
+ if (textureMesh.state == Mesh.MeshStates.LOADED) {
+ textureMesh.unload()
+ textureMesh = SimpleTextureMesh()
+ }
+ prepare(textureMesh)
+ textureMesh.load()
+ }
+
+ override fun prepare(mesh: SimpleTextureMesh) {
if (currentText == null) {
- return
+ currentText = getChatComponent()
}
renderChatComponent(currentText!!)
for (element in elements) {
- element.prepare()
+ element.prepare(mesh)
}
+ super.prepare()
}
- fun getTextComponent(): ChatComponent {
+ fun getChatComponent(): ChatComponent {
return ChatComponent.of(contents, translator = hudRenderer.connection.version.localeManager.language, hudTextTranslator = hudRenderer.hudTextTranslator)
}
@@ -166,13 +176,23 @@ class HUDTextElement : HUDElement {
if (!isEnabled) {
return
}
- val newText = getTextComponent()
+ val newText = getChatComponent()
if (currentText != newText) {
currentText = newText
prepareNext = true
}
}
+ override fun getPositionAtAnchor(anchor: HUDElementPositionAnchors): Vec2i {
+ return when (anchor) {
+ HUDElementPositionAnchors.CENTER -> TODO()
+ HUDElementPositionAnchors.TOP_LEFT -> super.getPositionAtAnchor(anchor)
+ HUDElementPositionAnchors.TOP_RIGHT -> Vec2i(elements[elements.lastIndex].getPositionAtAnchor(anchor).y, super.getPositionAtAnchor(anchor).x)
+ HUDElementPositionAnchors.BOTTOM_LEFT -> Vec2i(super.getPositionAtAnchor(anchor).x, elements[elements.lastIndex].getPositionAtAnchor(anchor).y)
+ HUDElementPositionAnchors.BOTTOM_RIGHT -> elements[elements.lastIndex].getPositionAtAnchor(anchor)
+ }
+ }
+
companion object {
val BETWEEN_CHARS_OFFSET = HUDElementVec2(Vec2(1, 0), HUDElementPositionUnits.SCALED_PIXELS)
}
diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextTranslator.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextTranslator.kt
index b115f8aaa..66c9600f3 100644
--- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextTranslator.kt
+++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextTranslator.kt
@@ -18,40 +18,74 @@ import de.bixilon.minosoft.data.locale.minecraft.Translator
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.TextComponent
+import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer
import de.bixilon.minosoft.gui.rendering.util.VecUtil.round
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
+import de.bixilon.minosoft.util.MMath.nanosToMillis
import de.bixilon.minosoft.util.MMath.round
-class HUDTextTranslator(val connection: PlayConnection) : Translator {
+class HUDTextTranslator(private val connection: PlayConnection) : Translator {
+ private lateinit var worldRenderer: WorldRenderer
+
override fun translate(key: String?, parent: TextComponent?, vararg data: Any?): ChatComponent {
if (key == null) {
return ChatComponent.of(key)
}
+ if (!this::worldRenderer.isInitialized) {
+ worldRenderer = connection.rendering!!.renderWindow.rendererMap[WorldRenderer.RESOURCE_LOCATION]!! as WorldRenderer
+ }
val resourceLocation = ResourceLocation(key)
if (resourceLocation !in insertRunnables) {
return ChatComponent.of(key)
}
val runnable = insertRunnables[resourceLocation]!! // checked before
- return ChatComponent.of(runnable.invoke(connection))
+ return ChatComponent.of(runnable.invoke(connection, worldRenderer))
}
companion object {
- private val insertRunnables = mutableMapOf String>()
+ private val insertRunnables = mutableMapOf String>()
init {
- insertRunnables[ResourceLocation("minosoft:playerPosition_x")] = { connection ->
+ //position
+ insertRunnables[ResourceLocation("minosoft:playerPosition_x")] = { connection, _ ->
connection.player.position.x.round(ROUND_DIGITS).toString()
}
- insertRunnables[ResourceLocation("minosoft:playerPosition_y")] = { connection ->
+ insertRunnables[ResourceLocation("minosoft:playerPosition_y")] = { connection, _ ->
connection.player.position.y.round(ROUND_DIGITS).toString()
}
- insertRunnables[ResourceLocation("minosoft:playerPosition_z")] = { connection ->
+ insertRunnables[ResourceLocation("minosoft:playerPosition_z")] = { connection, _ ->
connection.player.position.z.round(ROUND_DIGITS).toString()
}
- insertRunnables[ResourceLocation("minosoft:playerPosition_x")] = { connection ->
+ insertRunnables[ResourceLocation("minosoft:playerPosition_x")] = { connection, _ ->
connection.player.position.round(ROUND_DIGITS).toString()
}
+ // timings
+ insertRunnables[ResourceLocation("minosoft:fps")] = { connection, _ ->
+ connection.rendering!!.renderWindow.renderStats.fpsLastSecond.toString()
+ }
+ insertRunnables[ResourceLocation("minosoft:average_frame_time")] = { connection, _ ->
+ connection.rendering!!.renderWindow.renderStats.avgFrameTime.nanosToMillis.round(1).toString()
+ }
+ insertRunnables[ResourceLocation("minosoft:min_frame_time")] = { connection, _ ->
+ connection.rendering!!.renderWindow.renderStats.minFrameTime.nanosToMillis.round(1).toString()
+ }
+ insertRunnables[ResourceLocation("minosoft:max_frame_time")] = { connection, _ ->
+ connection.rendering!!.renderWindow.renderStats.maxFrameTime.nanosToMillis.round(1).toString()
+ }
+ // chunk data
+ insertRunnables[ResourceLocation("minosoft:queued_chunks_count")] = { _, worldRenderer ->
+ worldRenderer.queuedChunks.size.toString()
+ }
+ insertRunnables[ResourceLocation("minosoft:visible_chunks_count")] = { _, worldRenderer ->
+ worldRenderer.visibleChunks.size.toString()
+ }
+ insertRunnables[ResourceLocation("minosoft:all_chunk_secions_count")] = { _, worldRenderer ->
+ worldRenderer.allChunkSections.size.toString()
+ }
+ insertRunnables[ResourceLocation("minosoft:triangle_count")] = { _, worldRenderer ->
+ worldRenderer.triangles.toString()
+ }
}
const val ROUND_DIGITS = 2
diff --git a/src/main/java/de/bixilon/minosoft/util/MMath.kt b/src/main/java/de/bixilon/minosoft/util/MMath.kt
index 2dc3e362c..999bc76e3 100644
--- a/src/main/java/de/bixilon/minosoft/util/MMath.kt
+++ b/src/main/java/de/bixilon/minosoft/util/MMath.kt
@@ -111,4 +111,6 @@ object MMath {
val multiplicationFactor = glm.pow(10, digits)
return (this * multiplicationFactor).floor / multiplicationFactor
}
+
+ val Long.nanosToMillis: Float get() = this / 1E6f
}