hud: add relative element positioning

This commit is contained in:
Lukas 2021-06-11 22:32:38 +02:00
parent 0c75b50093
commit 5608a9ff4d
8 changed files with 58 additions and 17 deletions

View File

@ -14,16 +14,17 @@
package de.bixilon.minosoft.config.config.game package de.bixilon.minosoft.config.config.game
import de.bixilon.minosoft.config.config.game.controls.ControlsGameConfig import de.bixilon.minosoft.config.config.game.controls.ControlsGameConfig
import de.bixilon.minosoft.config.config.game.elements.ElementsGameConfig
import de.bixilon.minosoft.config.config.game.graphics.GraphicsGameConfig import de.bixilon.minosoft.config.config.game.graphics.GraphicsGameConfig
import de.bixilon.minosoft.config.config.game.sound.SoundConfig import de.bixilon.minosoft.config.config.game.sound.SoundConfig
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.HUDElement
data class GameConfig( data class GameConfig(
var graphics: GraphicsGameConfig = GraphicsGameConfig(), var graphics: GraphicsGameConfig = GraphicsGameConfig(),
var other: OtherGameConfig = OtherGameConfig(), var other: OtherGameConfig = OtherGameConfig(),
var hud: HUDGameConfig = HUDGameConfig(), var hud: HUDGameConfig = HUDGameConfig(),
var controls: ControlsGameConfig = ControlsGameConfig(), var controls: ControlsGameConfig = ControlsGameConfig(),
var elements: ElementsGameConfig = ElementsGameConfig(), var elements: MutableMap<ResourceLocation, HUDElement> = mutableMapOf(),
var camera: CameraGameConfig = CameraGameConfig(), var camera: CameraGameConfig = CameraGameConfig(),
var sound: SoundConfig = SoundConfig(), var sound: SoundConfig = SoundConfig(),
) )

View File

@ -67,7 +67,7 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
} }
private fun registerElements() { private fun registerElements() {
for ((resourceLocation, hudElement) in Minosoft.getConfig().config.game.elements.entries.entries) { for ((resourceLocation, hudElement) in Minosoft.getConfig().config.game.elements.entries) {
hudElements[resourceLocation] = hudElement hudElements[resourceLocation] = hudElement
enabledHUDElements[resourceLocation] = hudElement enabledHUDElements[resourceLocation] = hudElement
hudElement.init(this) hudElement.init(this)

View File

@ -1,12 +1,15 @@
package de.bixilon.minosoft.gui.rendering.hud.elements.position package de.bixilon.minosoft.gui.rendering.hud.elements.position
import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.gui.rendering.util.VecUtil.ONES
import glm_.vec2.Vec2
import glm_.vec2.Vec2i import glm_.vec2.Vec2i
enum class HUDElementPositionAnchors( enum class HUDElementPositionAnchors(
val resourceLocation: ResourceLocation, val resourceLocation: ResourceLocation,
val quadTransform: (Vec2i, Vec2i) -> Array<Vec2i>, val quadTransform: (Vec2i, Vec2i) -> Array<Vec2i>,
val positionTransform: (Vec2i) -> Vec2i val positionTransform: Vec2
) { ) {
CENTER(ResourceLocation("minosoft:center"), CENTER(ResourceLocation("minosoft:center"),
{ position, size -> { position, size ->
@ -16,8 +19,28 @@ enum class HUDElementPositionAnchors(
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),
) }, ) },
{ size -> size * 0.5f } Vec2(0.5f, 0.5f)
) ),
TOP_LEFT(ResourceLocation("minosoft:top_left"),
{ position, size ->
arrayOf(
position + size,
Vec2i(position.x + size.x, position.y),
Vec2i(position.x, position.y + size.y),
position,
) },
Vec2.EMPTY
),
BOTTOM_RIGHT(ResourceLocation("minosoft:bottom_right"),
{ position, size ->
arrayOf(
position,
Vec2i(position.x, position.y - size.y),
Vec2i(position.x - size.x, position.y),
position - size,
) },
Vec2.ONES
),
; ;
companion object { companion object {
val HUD_ELEMENT_POSITION_ATTACHMENT_OPTIONS = values() val HUD_ELEMENT_POSITION_ATTACHMENT_OPTIONS = values()

View File

@ -13,10 +13,10 @@ enum class HUDElementPositionUnits(val abbreviation: String, val realPositionCon
it * Minosoft.getConfig().config.game.hud.scale it * Minosoft.getConfig().config.game.hud.scale
}), }),
UNIT("%", { it, hudRenderer, axis -> UNIT("%", { it, hudRenderer, axis ->
it * hudRenderer.renderWindow.screenDimensions[axis] / TOTAL_UNITS it * hudRenderer.renderWindow.screenDimensions[axis].toFloat() / TOTAL_UNITS
}), }),
SCALED_UNIT("%s", { it, hudRenderer, axis -> SCALED_UNIT("%s", { it, hudRenderer, axis ->
it * hudRenderer.renderWindow.screenDimensions[axis] / TOTAL_UNITS * Minosoft.getConfig().config.game.hud.scale it * hudRenderer.renderWindow.screenDimensions[axis].toFloat() / TOTAL_UNITS * Minosoft.getConfig().config.game.hud.scale
}) })
; ;
@ -28,7 +28,7 @@ enum class HUDElementPositionUnits(val abbreviation: String, val realPositionCon
return stringValue.toFloatOrNull() ?: throw IllegalArgumentException("unknown value $string") return stringValue.toFloatOrNull() ?: throw IllegalArgumentException("unknown value $string")
} }
private val UNIT_REGEX = Regex("(?!\\d+(.?\\d+))\\D+\\B") private val UNIT_REGEX = Regex("(?!-?\\d+(.?\\d+))\\D+")
fun deserialize(string: String): HUDElementPositionUnits { fun deserialize(string: String): HUDElementPositionUnits {
val stringValue = UNIT_REGEX.find(string)?.value ?: throw IllegalArgumentException("unknown value $string") val stringValue = UNIT_REGEX.find(string)?.value ?: throw IllegalArgumentException("unknown value $string")

View File

@ -16,6 +16,7 @@ package de.bixilon.minosoft.gui.rendering.hud.elements.primitive
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer 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.HUDElementPositionAnchors
import de.bixilon.minosoft.gui.rendering.hud.elements.position.HUDElementVec2 import de.bixilon.minosoft.gui.rendering.hud.elements.position.HUDElementVec2
import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec2
import glm_.mat4x4.Mat4 import glm_.mat4x4.Mat4
import glm_.vec2.Vec2i import glm_.vec2.Vec2i
@ -35,9 +36,10 @@ abstract class HUDElement(
open fun draw() {} open fun draw() {}
open fun prepare(matrix: Mat4) {} open fun prepare(matrix: Mat4) {}
fun getPositionAtAnchor(anchor: HUDElementPositionAnchors, hudRenderer: HUDRenderer): Vec2i { fun getPositionAtAnchor(anchor: HUDElementPositionAnchors, hudRenderer: HUDRenderer): Vec2i {
return position.getRealPosition(hudRenderer) - val realSize = size.getRealVector(hudRenderer).toVec2
position.anchor.positionTransform.invoke(size.getRealVector(hudRenderer)) + val realPosition = position.getRealPosition(hudRenderer)
anchor.positionTransform.invoke(size.getRealVector(hudRenderer)) return realPosition - realSize * position.anchor.positionTransform + realSize * anchor.positionTransform
} }
} }

View File

@ -11,11 +11,12 @@ class HUDElementPosition(
val position: HUDElementVec2, val position: HUDElementVec2,
val anchor: HUDElementPositionAnchors, val anchor: HUDElementPositionAnchors,
val parent: String?, val parent: String?,
val parentAnchor: HUDElementPositionAnchors?,
) { ) {
var parentElement: HUDElement? = null var parentElement: HUDElement? = null
fun init() { fun init() {
parentElement = parent?.let { Minosoft.getConfig().config.game.elements.entries[ResourceLocation(it)] } parentElement = parent?.let { Minosoft.getConfig().config.game.elements[ResourceLocation(it)] }
} }
fun getPositions(hudRenderer: HUDRenderer, size: Vec2i): Array<Vec2i> { fun getPositions(hudRenderer: HUDRenderer, size: Vec2i): Array<Vec2i> {
@ -27,7 +28,7 @@ class HUDElementPosition(
if (parentElement == null) { if (parentElement == null) {
return position.getRealVector(hudRenderer) return position.getRealVector(hudRenderer)
} }
return parentElement!!.getPositionAtAnchor(anchor, hudRenderer) + position.getRealVector(hudRenderer) return position.getRealVector(hudRenderer) + parentElement!!.getPositionAtAnchor(parentAnchor!!, hudRenderer)
} }
companion object { companion object {
@ -35,8 +36,10 @@ class HUDElementPosition(
val position = HUDElementVec2.deserialize(json)!! val position = HUDElementVec2.deserialize(json)!!
val positionAnchor = HUDElementPositionAnchors.HUD_ELEMENT_POSITION_ATTACHMENTS_MAPPING[ResourceLocation(json["anchor"].toString())]!! val positionAnchor = HUDElementPositionAnchors.HUD_ELEMENT_POSITION_ATTACHMENTS_MAPPING[ResourceLocation(json["anchor"].toString())]!!
val parent = json["parent"] as String? val parent = json["parent"] as String?
val parentAnchor = json["parent_anchor"]?.let {
return HUDElementPosition(position, positionAnchor, parent) HUDElementPositionAnchors.HUD_ELEMENT_POSITION_ATTACHMENTS_MAPPING[ResourceLocation(it.toString())]
}
return HUDElementPosition(position, positionAnchor, parent, parentAnchor)
} }
} }
} }

View File

@ -25,7 +25,7 @@ class HUDImageElement: HUDElement {
val tint: RGBColor val tint: RGBColor
constructor(position: HUDElementPosition, size: HUDElementVec2, json: Map<String, Any>? = null): super(position, size) { constructor(position: HUDElementPosition, size: HUDElementVec2, json: Map<String, Any>? = null): super(position, size) {
z = (json?.get("z") as Int?) ?: 0 z = (json?.get("z") as Double?)?.toInt() ?: 0
textureName = (json?.get("texture") as String?)?.let { ResourceLocation(it) } textureName = (json?.get("texture") as String?)?.let { ResourceLocation(it) }
tint = json?.get("tint")?.let{ RGBColorSerializer.fromJsonValue(it) } ?: ChatColors.WHITE tint = json?.get("tint")?.let{ RGBColorSerializer.fromJsonValue(it) } ?: ChatColors.WHITE
} }

View File

@ -46,6 +46,16 @@ object VecUtil {
val Vec3.Companion.ONE: Vec3 val Vec3.Companion.ONE: Vec3
get() = Vec3(1, 1, 1) get() = Vec3(1, 1, 1)
val Vec2i.Companion.EMPTY: Vec2i
get() = Vec2i(0, 0)
val Vec2.Companion.EMPTY: Vec2
get() = Vec2(0, 0)
val Vec2.Companion.ONES: Vec2
get() = Vec2(1f, 1f)
fun JsonElement.toVec3(): Vec3 { fun JsonElement.toVec3(): Vec3 {
return when (this) { return when (this) {
is JsonArray -> Vec3(this[0].asFloat, this[1].asFloat, this[2].asFloat) is JsonArray -> Vec3(this[0].asFloat, this[1].asFloat, this[2].asFloat)
@ -344,4 +354,6 @@ object VecUtil {
Axes.Z -> throw java.lang.IllegalArgumentException("Z does not exist") Axes.Z -> throw java.lang.IllegalArgumentException("Z does not exist")
} }
} }
val Vec2i.toVec2: Vec2 get() = Vec2(this)
} }