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
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.sound.SoundConfig
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.HUDElement
data class GameConfig(
var graphics: GraphicsGameConfig = GraphicsGameConfig(),
var other: OtherGameConfig = OtherGameConfig(),
var hud: HUDGameConfig = HUDGameConfig(),
var controls: ControlsGameConfig = ControlsGameConfig(),
var elements: ElementsGameConfig = ElementsGameConfig(),
var elements: MutableMap<ResourceLocation, HUDElement> = mutableMapOf(),
var camera: CameraGameConfig = CameraGameConfig(),
var sound: SoundConfig = SoundConfig(),
)

View File

@ -67,7 +67,7 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
}
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
enabledHUDElements[resourceLocation] = hudElement
hudElement.init(this)

View File

@ -1,12 +1,15 @@
package de.bixilon.minosoft.gui.rendering.hud.elements.position
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
enum class HUDElementPositionAnchors(
val resourceLocation: ResourceLocation,
val quadTransform: (Vec2i, Vec2i) -> Array<Vec2i>,
val positionTransform: (Vec2i) -> Vec2i
val positionTransform: Vec2
) {
CENTER(ResourceLocation("minosoft:center"),
{ 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),
) },
{ 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 {
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
}),
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 ->
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")
}
private val UNIT_REGEX = Regex("(?!\\d+(.?\\d+))\\D+\\B")
private val UNIT_REGEX = Regex("(?!-?\\d+(.?\\d+))\\D+")
fun deserialize(string: String): HUDElementPositionUnits {
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.elements.position.HUDElementPositionAnchors
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_.vec2.Vec2i
@ -35,9 +36,10 @@ abstract class HUDElement(
open fun draw() {}
open fun prepare(matrix: Mat4) {}
fun getPositionAtAnchor(anchor: HUDElementPositionAnchors, hudRenderer: HUDRenderer): Vec2i {
return position.getRealPosition(hudRenderer) -
position.anchor.positionTransform.invoke(size.getRealVector(hudRenderer)) +
anchor.positionTransform.invoke(size.getRealVector(hudRenderer))
val realSize = size.getRealVector(hudRenderer).toVec2
val realPosition = position.getRealPosition(hudRenderer)
return realPosition - realSize * position.anchor.positionTransform + realSize * anchor.positionTransform
}
}

View File

@ -11,11 +11,12 @@ class HUDElementPosition(
val position: HUDElementVec2,
val anchor: HUDElementPositionAnchors,
val parent: String?,
val parentAnchor: HUDElementPositionAnchors?,
) {
var parentElement: HUDElement? = null
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> {
@ -27,7 +28,7 @@ class HUDElementPosition(
if (parentElement == null) {
return position.getRealVector(hudRenderer)
}
return parentElement!!.getPositionAtAnchor(anchor, hudRenderer) + position.getRealVector(hudRenderer)
return position.getRealVector(hudRenderer) + parentElement!!.getPositionAtAnchor(parentAnchor!!, hudRenderer)
}
companion object {
@ -35,8 +36,10 @@ class HUDElementPosition(
val position = HUDElementVec2.deserialize(json)!!
val positionAnchor = HUDElementPositionAnchors.HUD_ELEMENT_POSITION_ATTACHMENTS_MAPPING[ResourceLocation(json["anchor"].toString())]!!
val parent = json["parent"] as String?
return HUDElementPosition(position, positionAnchor, parent)
val parentAnchor = json["parent_anchor"]?.let {
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
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) }
tint = json?.get("tint")?.let{ RGBColorSerializer.fromJsonValue(it) } ?: ChatColors.WHITE
}

View File

@ -46,6 +46,16 @@ object VecUtil {
val Vec3.Companion.ONE: Vec3
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 {
return when (this) {
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")
}
}
val Vec2i.toVec2: Vec2 get() = Vec2(this)
}