rendering: introduce new hud system

This commit is contained in:
Lukas 2021-05-29 15:32:28 +02:00
parent 07587367bb
commit 18247ebfb8
10 changed files with 264 additions and 1 deletions

View File

@ -21,6 +21,7 @@ import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Renderer
import de.bixilon.minosoft.gui.rendering.RendererBuilder
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.HUDElement
import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
import de.bixilon.minosoft.gui.rendering.shader.Shader
@ -68,7 +69,7 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
}
private fun registerElements() {
for ((resourceLocation, hudElement) in Minosoft.getConfig().config.game.elements.entries) {
for ((resourceLocation, hudElement) in Minosoft.getConfig().config.game.elements.entries.entries) {
hudElements[resourceLocation] = hudElement
enabledHUDElements[resourceLocation] = hudElement
hudElement.init(this)

View File

@ -32,6 +32,15 @@ data class HUDAtlasElement(
override val size: Vec2i
get() = binding.size
val uvs: Array<Vec2> get() {
return arrayOf(
Vec2(uvStart.x, uvStart.y),
Vec2(uvStart.x, uvEnd.y),
Vec2(uvEnd.x, uvStart.y),
Vec2(uvEnd.x, uvEnd.y),
)
}
fun postInit() {
uvStart = (Vec2(binding.start) + RenderConstants.PIXEL_UV_PIXEL_ADD) * texture.arraySinglePixelFactor
uvEnd = Vec2(binding.end) * texture.arraySinglePixelFactor

View File

@ -0,0 +1,27 @@
package de.bixilon.minosoft.gui.rendering.hud.nodes.position
import de.bixilon.minosoft.data.mappings.ResourceLocation
import glm_.vec2.Vec2i
enum class HUDElementPositionAnchors(val resourceLocation: ResourceLocation, val quadTransform: (Vec2i, Vec2i) -> Array<Vec2i>) {
CENTER(ResourceLocation("minosoft:center"), { position, size ->
arrayOf(
Vec2i(position.x + size.x * 0.5f, position.y + size.y * 0.5f),
Vec2i(position.x + size.x * 0.5f, position.y - size.y * 0.5f),
Vec2i(position.x - size.x * 0.5f, position.y + size.y * 0.5f),
Vec2i(position.x - size.x * 0.5f, position.y - size.y * 0.5f),
)
})
;
companion object {
val HUD_ELEMENT_POSITION_ATTACHMENT_OPTIONS = values()
val HUD_ELEMENT_POSITION_ATTACHMENTS_MAPPING = run {
val result = mutableMapOf<ResourceLocation, HUDElementPositionAnchors>()
for (hudPositionAttachmentOption in HUD_ELEMENT_POSITION_ATTACHMENT_OPTIONS) {
result[hudPositionAttachmentOption.resourceLocation] = hudPositionAttachmentOption
}
result
}
}
}

View File

@ -0,0 +1,37 @@
package de.bixilon.minosoft.gui.rendering.hud.nodes.position
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.util.VecUtil.get
enum class HUDElementPositionUnits(val resourceLocation: ResourceLocation, val realPositionConversion: (Float, HUDRenderer, Axes) -> Float) {
PIXELS(ResourceLocation("minosoft:pixel"), { it, _, _ ->
it
}),
SCALED_PIXELS(ResourceLocation("minosoft:scaled_pixel"), { it, _, _ ->
it * Minosoft.getConfig().config.game.hud.scale
}),
UNIT(ResourceLocation("minosoft:unit"), { it, hudRenderer, axis ->
it * hudRenderer.renderWindow.screenDimensions[axis] / TOTAL_UNITS
}),
SCALED_UNIT(ResourceLocation("minosoft:scaled_unit"), { it, hudRenderer, axis ->
it * hudRenderer.renderWindow.screenDimensions[axis] / TOTAL_UNITS * Minosoft.getConfig().config.game.hud.scale
})
;
companion object {
val HUD_ELEMENT_POSITION_UNITS = values()
val HUD_ELEMENT_POSITION_MAP = run {
val result = mutableMapOf<ResourceLocation, HUDElementPositionUnits>()
for (unit in HUD_ELEMENT_POSITION_UNITS) {
result[unit.resourceLocation] = unit
}
result
}
const val TOTAL_UNITS = 100f
}
}

View File

@ -0,0 +1,33 @@
package de.bixilon.minosoft.gui.rendering.hud.nodes.position
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import glm_.vec2.Vec2i
class HUDElementVec2(
val x: Float,
val xUnit: HUDElementPositionUnits,
val y: Float,
val yUnit: HUDElementPositionUnits,
) {
fun getRealVector(hudRenderer: HUDRenderer): Vec2i {
return Vec2i(
xUnit.realPositionConversion.invoke(x, hudRenderer, Axes.X),
yUnit.realPositionConversion.invoke(y, hudRenderer, Axes.Y)
)
}
companion object {
fun deserialize(data: Any?): HUDElementVec2? {
if (data !is Map<*, *>) {
return null
}
val x = (data["x"] as Double).toFloat()
val xUnit = HUDElementPositionUnits.HUD_ELEMENT_POSITION_MAP[ResourceLocation(data["x_unit"].toString())] ?: HUDElementPositionUnits.PIXELS
val y = (data["x"] as Double).toFloat()
val yUnit = HUDElementPositionUnits.HUD_ELEMENT_POSITION_MAP[ResourceLocation(data["y_unit"].toString())] ?: HUDElementPositionUnits.PIXELS
return HUDElementVec2(x, xUnit, y, yUnit)
}
}
}

View File

@ -0,0 +1,42 @@
/*
* Minosoft
* Copyright (C) 2021 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.hud.nodes.primitive
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.nodes.position.HUDElementPositionAnchors
import de.bixilon.minosoft.gui.rendering.hud.nodes.position.HUDElementVec2
import glm_.mat4x4.Mat4
abstract class HUDElement(
val position: HUDElementVec2,
val positionAnchor: HUDElementPositionAnchors,
val content: ResourceLocation,
val size: HUDElementVec2,
val realZ: Float,
val tint: RGBColor,
) {
lateinit var hudRenderer: HUDRenderer
open fun init(hudRenderer: HUDRenderer) {
this.hudRenderer = hudRenderer
}
open fun postInit() {}
open fun draw() {}
open fun prepare(matrix: Mat4) {}
}

View File

@ -0,0 +1,35 @@
package de.bixilon.minosoft.gui.rendering.hud.nodes.primitive
import com.squareup.moshi.FromJson
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.ToJson
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.hud.nodes.position.HUDElementPositionAnchors
import de.bixilon.minosoft.gui.rendering.hud.nodes.position.HUDElementVec2
import de.bixilon.minosoft.util.json.RGBColorSerializer
object HUDElementSerializer {
@FromJson
fun fromJson(json: Map<String, Any>): HUDElement? {
val position = HUDElementVec2.deserialize(json["position"])
val positionAnchor = HUDElementPositionAnchors.HUD_ELEMENT_POSITION_ATTACHMENTS_MAPPING[ResourceLocation((json["position"] as Map<*,*>)["location"].toString())]!!
val size = HUDElementVec2.deserialize(json["size"])
return HUD_ELEMENT_TYPES[ResourceLocation(json["type"].toString())]?.constructors?.first()?.call(
position,
positionAnchor,
ResourceLocation(json["content"].toString()),
size,
(json["real_z"] as Double).toFloat(),
json["tint"]?.let{ RGBColorSerializer.fromJsonValue(it) },
)
}
@ToJson
fun toJson(jsonWriter: JsonWriter, hudElement: HUDElement?) {
}
private val HUD_ELEMENT_TYPES = mutableMapOf(
ResourceLocation("minosoft:image_element") to HUDImageElement::class,
// modding here!
)
}

View File

@ -0,0 +1,62 @@
package de.bixilon.minosoft.gui.rendering.hud.nodes.primitive
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.text.ChatColors
import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.position.HUDElementPositionAnchors
import de.bixilon.minosoft.gui.rendering.hud.nodes.position.HUDElementVec2
import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
import de.bixilon.minosoft.gui.rendering.util.mesh.SimpleTextureMesh
import glm_.mat4x4.Mat4
import glm_.vec2.Vec2
import glm_.vec3.Vec3
import glm_.vec4.Vec4
import glm_.vec4.swizzle.xy
class HUDImageElement(
position: HUDElementVec2,
positionAnchor: HUDElementPositionAnchors,
content: ResourceLocation,
size: HUDElementVec2,
realZ: Float,
tint: RGBColor = ChatColors.WHITE,
) : HUDElement(position, positionAnchor, content, size, realZ, tint) {
private var mesh = SimpleTextureMesh()
private lateinit var hudAtlasElement: HUDAtlasElement
override fun init(hudRenderer: HUDRenderer) {
super.init(hudRenderer)
hudAtlasElement = hudRenderer.hudAtlasElements[content]!!
}
override fun draw() {
mesh.draw()
}
override fun prepare(matrix: Mat4) {
super.prepare(matrix)
if (mesh.state == Mesh.MeshStates.LOADED) {
mesh.unload()
mesh = SimpleTextureMesh()
}
val realPosition = position.getRealVector(hudRenderer)
val realSize = size.getRealVector(hudRenderer)
fun addVertex(position: Vec2, textureUV: Vec2) {
mesh.addVertex(Vec3(
position.x,
position.y,
realZ,
), hudAtlasElement.texture, textureUV, tint)
}
val positions = positionAnchor.quadTransform.invoke(realPosition, realSize)
val uvs = hudAtlasElement.uvs
for (position in arrayOf(0, 1, 2, 1, 3, 2)) {
addVertex((matrix * Vec4(positions[position], 1f, 1f)).xy, uvs[position])
}
mesh.load()
}
}

View File

@ -514,4 +514,20 @@ object VecUtil {
z = 0.0
}
}
operator fun Vec2i.get(axis: Axes): Int {
return when (axis) {
Axes.X -> this.x
Axes.Y -> this.y
Axes.Z -> throw java.lang.IllegalArgumentException("Z does not exist")
}
}
operator fun Vec2.get(axis: Axes): Float {
return when (axis) {
Axes.X -> this.x
Axes.Y -> this.y
Axes.Z -> throw java.lang.IllegalArgumentException("Z does not exist")
}
}
}

View File

@ -18,6 +18,7 @@ import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import de.bixilon.minosoft.config.config.Config
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.HUDElementSerializer
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.HUDElementSerializer
import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties