mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 03:44:54 -04:00
rendering: introduce new hud system
This commit is contained in:
parent
8eee74df5d
commit
66a726423e
@ -14,8 +14,8 @@
|
|||||||
package de.bixilon.minosoft.config.config.game.elements
|
package de.bixilon.minosoft.config.config.game.elements
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.HUDElement
|
||||||
|
|
||||||
data class ElementsGameConfig(
|
data class ElementsGameConfig(
|
||||||
val entries: MutableMap<ResourceLocation, HUDElementProperties> = mutableMapOf(),
|
val entries: MutableMap<ResourceLocation, HUDElement> = mutableMapOf(),
|
||||||
)
|
)
|
||||||
|
@ -17,12 +17,7 @@ import com.google.gson.JsonElement
|
|||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import de.bixilon.minosoft.data.locale.minecraft.Translator
|
import de.bixilon.minosoft.data.locale.minecraft.Translator
|
||||||
import de.bixilon.minosoft.data.text.RGBColor.Companion.asColor
|
import de.bixilon.minosoft.data.text.RGBColor.Companion.asColor
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
|
||||||
import de.bixilon.minosoft.gui.rendering.font.text.TextGetProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.font.text.TextSetProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
|
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
import javafx.collections.ObservableList
|
import javafx.collections.ObservableList
|
||||||
import javafx.scene.Node
|
import javafx.scene.Node
|
||||||
import java.text.CharacterIterator
|
import java.text.CharacterIterator
|
||||||
@ -178,12 +173,6 @@ class BaseComponent : ChatComponent {
|
|||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun prepareRender(startPosition: Vec2i, offset: Vec2i, renderWindow: RenderWindow, textElement: LabelNode, z: Int, setProperties: TextSetProperties, getProperties: TextGetProperties) {
|
|
||||||
for (part in parts) {
|
|
||||||
part.prepareRender(startPosition, offset, renderWindow, textElement, z, setProperties, getProperties)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun applyDefaultColor(color: RGBColor) {
|
override fun applyDefaultColor(color: RGBColor) {
|
||||||
for (part in parts) {
|
for (part in parts) {
|
||||||
part.applyDefaultColor(color)
|
part.applyDefaultColor(color)
|
||||||
|
@ -17,11 +17,6 @@ import com.google.gson.JsonObject
|
|||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
import com.google.gson.JsonPrimitive
|
import com.google.gson.JsonPrimitive
|
||||||
import de.bixilon.minosoft.data.locale.minecraft.Translator
|
import de.bixilon.minosoft.data.locale.minecraft.Translator
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
|
||||||
import de.bixilon.minosoft.gui.rendering.font.text.TextGetProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.font.text.TextSetProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
|
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
import javafx.collections.FXCollections
|
import javafx.collections.FXCollections
|
||||||
import javafx.collections.ObservableList
|
import javafx.collections.ObservableList
|
||||||
import javafx.scene.Node
|
import javafx.scene.Node
|
||||||
@ -59,11 +54,6 @@ interface ChatComponent {
|
|||||||
fun applyDefaultColor(color: RGBColor)
|
fun applyDefaultColor(color: RGBColor)
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares the chat component for rendering (used in opengl)
|
|
||||||
*/
|
|
||||||
fun prepareRender(startPosition: Vec2i, offset: Vec2i, renderWindow: RenderWindow, textElement: LabelNode, z: Int, setProperties: TextSetProperties, getProperties: TextGetProperties)
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
|
@ -13,17 +13,8 @@
|
|||||||
package de.bixilon.minosoft.data.text
|
package de.bixilon.minosoft.data.text
|
||||||
|
|
||||||
import de.bixilon.minosoft.Minosoft
|
import de.bixilon.minosoft.Minosoft
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
|
||||||
import de.bixilon.minosoft.gui.rendering.font.Font
|
|
||||||
import de.bixilon.minosoft.gui.rendering.font.text.TextGetProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.font.text.TextSetProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.ImageNode
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import de.bixilon.minosoft.util.Util
|
import de.bixilon.minosoft.util.Util
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
import javafx.animation.Animation
|
import javafx.animation.Animation
|
||||||
import javafx.animation.KeyFrame
|
import javafx.animation.KeyFrame
|
||||||
import javafx.animation.Timeline
|
import javafx.animation.Timeline
|
||||||
@ -161,52 +152,4 @@ open class TextComponent(
|
|||||||
nodes.add(text)
|
nodes.add(text)
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun prepareRender(startPosition: Vec2i, offset: Vec2i, renderWindow: RenderWindow, textElement: LabelNode, z: Int, setProperties: TextSetProperties, getProperties: TextGetProperties) {
|
|
||||||
val color = this.color ?: ProtocolDefinition.DEFAULT_COLOR
|
|
||||||
|
|
||||||
|
|
||||||
// bring chars in right order and reverse them if right bound
|
|
||||||
val charArray = this.message.toCharArray().toList()
|
|
||||||
|
|
||||||
fun checkGetSize(charEnd: Vec2i) {
|
|
||||||
if (charEnd.x > getProperties.size.x) {
|
|
||||||
getProperties.size.x = charEnd.x
|
|
||||||
}
|
|
||||||
if (charEnd.y > getProperties.size.y) {
|
|
||||||
getProperties.size.y = charEnd.y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun pushNewLine() {
|
|
||||||
offset.x = 0
|
|
||||||
offset.y += Font.CHAR_HEIGHT + RenderConstants.TEXT_LINE_PADDING
|
|
||||||
|
|
||||||
checkGetSize(Vec2i(0, 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
// add all chars
|
|
||||||
for (char in charArray) {
|
|
||||||
if (ProtocolDefinition.LINE_BREAK_CHARS.contains(char)) {
|
|
||||||
pushNewLine()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
val fontChar = renderWindow.font.getChar(char)
|
|
||||||
val charSize = fontChar.size
|
|
||||||
|
|
||||||
var charStart = Vec2i(offset)
|
|
||||||
var charEnd = charStart + charSize
|
|
||||||
|
|
||||||
if (charEnd.x >= setProperties.hardWrap) {
|
|
||||||
pushNewLine()
|
|
||||||
charStart = Vec2i(offset)
|
|
||||||
charEnd = charStart + charSize
|
|
||||||
}
|
|
||||||
textElement.addChild(charStart + startPosition, ImageNode(renderWindow, NodeSizing(minSize = charSize), fontChar, 1, color))
|
|
||||||
offset.x += charSize.x + Font.SPACE_BETWEEN_CHARS
|
|
||||||
|
|
||||||
checkGetSize(charEnd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.gui.rendering.util.mesh.SimpleTextureMesh
|
|
||||||
|
|
||||||
class HUDMesh : SimpleTextureMesh() {
|
|
||||||
|
|
||||||
fun addCacheMesh(cacheMesh: HUDCacheMesh) {
|
|
||||||
data.addAll(cacheMesh.cache)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.mappings.CompanionResourceLocation
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
|
|
||||||
|
|
||||||
interface HUDRenderBuilder<T : HUDElement> : CompanionResourceLocation {
|
|
||||||
val DEFAULT_PROPERTIES: HUDElementProperties
|
|
||||||
|
|
||||||
fun build(hudRenderer: HUDRenderer): T
|
|
||||||
}
|
|
@ -21,120 +21,57 @@ import de.bixilon.minosoft.gui.rendering.RenderWindow
|
|||||||
import de.bixilon.minosoft.gui.rendering.Renderer
|
import de.bixilon.minosoft.gui.rendering.Renderer
|
||||||
import de.bixilon.minosoft.gui.rendering.RendererBuilder
|
import de.bixilon.minosoft.gui.rendering.RendererBuilder
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
|
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.elements.other.BreakProgressHUDElement
|
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.HUDElement
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.elements.other.CrosshairHUDElement
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.chat.ChatBoxHUDElement
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.debug.HUDSystemDebugNode
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.debug.HUDWorldDebugNode
|
|
||||||
import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
|
import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
|
||||||
import de.bixilon.minosoft.gui.rendering.shader.Shader
|
import de.bixilon.minosoft.gui.rendering.shader.Shader
|
||||||
import de.bixilon.minosoft.modding.event.CallbackEventInvoker
|
import de.bixilon.minosoft.modding.event.CallbackEventInvoker
|
||||||
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import de.bixilon.minosoft.util.MMath
|
|
||||||
import de.bixilon.minosoft.util.json.ResourceLocationJsonMap.toResourceLocationMap
|
import de.bixilon.minosoft.util.json.ResourceLocationJsonMap.toResourceLocationMap
|
||||||
import glm_.glm
|
import glm_.glm
|
||||||
import glm_.mat4x4.Mat4
|
import glm_.mat4x4.Mat4
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
|
|
||||||
class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow) : Renderer {
|
class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow) : Renderer {
|
||||||
private val hudElements: MutableMap<ResourceLocation, Pair<HUDElementProperties, HUDElement>> = mutableMapOf()
|
private val hudElements: MutableMap<ResourceLocation, HUDElement> = mutableMapOf()
|
||||||
private val enabledHUDElement: MutableMap<ResourceLocation, Pair<HUDElementProperties, HUDElement>> = mutableMapOf()
|
private val enabledHUDElements: MutableMap<ResourceLocation, HUDElement> = mutableMapOf()
|
||||||
private val hudShader = Shader(
|
private val hudShader = Shader(
|
||||||
resourceLocation = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "hud"),
|
resourceLocation = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "hud"),
|
||||||
)
|
)
|
||||||
lateinit var hudAtlasElements: Map<ResourceLocation, HUDAtlasElement>
|
lateinit var hudAtlasElements: Map<ResourceLocation, HUDAtlasElement>
|
||||||
var orthographicMatrix: Mat4 = Mat4()
|
var orthographicMatrix: Mat4 = Mat4()
|
||||||
private set
|
private set
|
||||||
var currentHUDMesh: HUDMesh = HUDMesh()
|
|
||||||
|
|
||||||
private var hudEnabled = true
|
private var hudEnabled = true
|
||||||
|
|
||||||
private var forcePrepare = true
|
|
||||||
|
|
||||||
|
|
||||||
override fun init() {
|
override fun init() {
|
||||||
hudShader.load(Minosoft.MINOSOFT_ASSETS_MANAGER)
|
hudShader.load(Minosoft.MINOSOFT_ASSETS_MANAGER)
|
||||||
|
|
||||||
this.hudAtlasElements = HUDAtlasElement.deserialize(Minosoft.MINOSOFT_ASSETS_MANAGER.readJsonAsset(ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "mapping/atlas.json")).toResourceLocationMap(), renderWindow.textures.allTextures)
|
hudAtlasElements = HUDAtlasElement.deserialize(Minosoft.MINOSOFT_ASSETS_MANAGER.readJsonAsset(ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "mapping/atlas.json")).toResourceLocationMap(), renderWindow.textures.allTextures)
|
||||||
|
|
||||||
|
registerElements()
|
||||||
|
|
||||||
registerDefaultElements()
|
|
||||||
|
|
||||||
renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.TOGGLE_HUD) {
|
renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.TOGGLE_HUD) {
|
||||||
hudEnabled = !hudEnabled
|
hudEnabled = !hudEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((_, element) in hudElements.values) {
|
|
||||||
element.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.CLOSE) {
|
renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.CLOSE) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> {
|
connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> {
|
||||||
orthographicMatrix = glm.ortho(-it.screenDimensions.x / 2.0f, it.screenDimensions.x / 2.0f, -it.screenDimensions.y / 2.0f, it.screenDimensions.y / 2.0f)
|
orthographicMatrix = glm.ortho(0f, renderWindow.screenDimensions.x.toFloat(), renderWindow.screenDimensions.y.toFloat(), 0f)
|
||||||
for ((_, hudElement) in hudElements.values) {
|
for (hudElement in hudElements.values) {
|
||||||
hudElement.layout.clearChildrenCache()
|
hudElement.prepare(orthographicMatrix)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerDefaultElements() {
|
private fun registerElements() {
|
||||||
addElement(BreakProgressHUDElement)
|
for ((resourceLocation, hudElement) in Minosoft.getConfig().config.game.elements.entries.entries) {
|
||||||
addElement(CrosshairHUDElement)
|
hudElements[resourceLocation] = hudElement
|
||||||
|
enabledHUDElements[resourceLocation] = hudElement
|
||||||
addElement(HUDWorldDebugNode)
|
hudElement.init(this)
|
||||||
addElement(HUDSystemDebugNode)
|
|
||||||
addElement(ChatBoxHUDElement)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addElement(builder: HUDRenderBuilder<*>) {
|
|
||||||
var needToSafeConfig = false
|
|
||||||
val properties = Minosoft.getConfig().config.game.elements.entries.getOrPut(builder.RESOURCE_LOCATION) {
|
|
||||||
needToSafeConfig = true
|
|
||||||
builder.DEFAULT_PROPERTIES
|
|
||||||
}
|
|
||||||
if (needToSafeConfig) {
|
|
||||||
Minosoft.getConfig().saveToFile()
|
|
||||||
}
|
|
||||||
val hudElement = builder.build(this)
|
|
||||||
hudElement.properties = properties
|
|
||||||
val pair = Pair(properties, hudElement)
|
|
||||||
hudElements[builder.RESOURCE_LOCATION] = pair
|
|
||||||
|
|
||||||
|
|
||||||
properties.toggleKeyBinding?.let {
|
|
||||||
// register key binding
|
|
||||||
renderWindow.inputHandler.registerKeyCallback(it) {
|
|
||||||
// ToDo: Use sticky
|
|
||||||
if (enabledHUDElement.contains(builder.RESOURCE_LOCATION)) {
|
|
||||||
enabledHUDElement.remove(builder.RESOURCE_LOCATION)
|
|
||||||
} else {
|
|
||||||
enabledHUDElement[builder.RESOURCE_LOCATION] = pair
|
|
||||||
}
|
|
||||||
forcePrepare = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (properties.enabled) {
|
|
||||||
enabledHUDElement[builder.RESOURCE_LOCATION] = pair
|
|
||||||
forcePrepare = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeElement(resourceLocation: ResourceLocation) {
|
|
||||||
val element = hudElements[resourceLocation] ?: return
|
|
||||||
|
|
||||||
element.first.toggleKeyBinding?.let {
|
|
||||||
renderWindow.inputHandler.unregisterKeyBinding(it)
|
|
||||||
}
|
|
||||||
enabledHUDElement.remove(resourceLocation)
|
|
||||||
hudElements.remove(resourceLocation)
|
|
||||||
forcePrepare = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun postInit() {
|
override fun postInit() {
|
||||||
@ -145,74 +82,17 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
|
|||||||
renderWindow.textures.use(hudShader)
|
renderWindow.textures.use(hudShader)
|
||||||
|
|
||||||
for (element in hudElements.values) {
|
for (element in hudElements.values) {
|
||||||
element.second.postInit()
|
element.postInit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun draw() {
|
override fun draw() {
|
||||||
if (!RenderConstants.RENDER_HUD) {
|
if (RenderConstants.RENDER_HUD && hudEnabled) {
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hudEnabled) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var needsUpdate = false
|
|
||||||
val tempMesh = HUDMesh()
|
|
||||||
|
|
||||||
for ((_, hudElement) in enabledHUDElement.values) {
|
|
||||||
hudElement.draw()
|
|
||||||
|
|
||||||
if (hudElement.layout.needsCacheUpdate()) {
|
|
||||||
needsUpdate = true
|
|
||||||
// break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (forcePrepare || needsUpdate) {
|
|
||||||
for ((elementProperties, hudElement) in enabledHUDElement.values) {
|
|
||||||
val realScaleFactor = elementProperties.scale * Minosoft.getConfig().config.game.hud.scale
|
|
||||||
val realSize = hudElement.layout.sizing.currentSize * realScaleFactor
|
|
||||||
realSize.x = MMath.clamp(realSize.x, hudElement.layout.sizing.minSize.x, hudElement.layout.sizing.maxSize.x)
|
|
||||||
realSize.y = MMath.clamp(realSize.y, hudElement.layout.sizing.minSize.y, hudElement.layout.sizing.maxSize.y)
|
|
||||||
|
|
||||||
val elementStart = getRealPosition(realSize, elementProperties, renderWindow.screenDimensions)
|
|
||||||
|
|
||||||
hudElement.layout.checkCache(elementStart, realScaleFactor, orthographicMatrix, 0)
|
|
||||||
tempMesh.addCacheMesh(hudElement.layout.cache)
|
|
||||||
}
|
|
||||||
currentHUDMesh.unload(false)
|
|
||||||
tempMesh.load()
|
|
||||||
currentHUDMesh = tempMesh
|
|
||||||
}
|
|
||||||
hudShader.use()
|
hudShader.use()
|
||||||
currentHUDMesh.draw()
|
for (hudElement in enabledHUDElements.values) {
|
||||||
|
hudElement.draw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun getRealPosition(elementSize: Vec2i, elementProperties: HUDElementProperties, screenDimensions: Vec2i): Vec2i {
|
|
||||||
val halfScreenDimensions = screenDimensions / 2
|
|
||||||
val halfElementSize = elementSize / 2
|
|
||||||
val realPosition = elementProperties.position * halfScreenDimensions
|
|
||||||
|
|
||||||
var x = realPosition.x
|
|
||||||
var y = realPosition.y
|
|
||||||
if (elementProperties.xBinding == HUDElementProperties.PositionBindings.FURTHEST_POINT_AWAY) {
|
|
||||||
if (elementProperties.position.x >= 0) {
|
|
||||||
x -= elementSize.x
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
x -= halfElementSize.x
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elementProperties.yBinding == HUDElementProperties.PositionBindings.FURTHEST_POINT_AWAY) {
|
|
||||||
if (elementProperties.position.y < 0) {
|
|
||||||
y += elementSize.y
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
y += halfElementSize.y
|
|
||||||
}
|
|
||||||
return Vec2i(x, y)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : RendererBuilder<HUDRenderer> {
|
companion object : RendererBuilder<HUDRenderer> {
|
||||||
|
@ -32,6 +32,14 @@ data class HUDAtlasElement(
|
|||||||
override val size: Vec2i
|
override val size: Vec2i
|
||||||
get() = binding.size
|
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() {
|
fun postInit() {
|
||||||
uvStart = (Vec2(binding.start) + RenderConstants.PIXEL_UV_PIXEL_ADD) * texture.arraySinglePixelFactor
|
uvStart = (Vec2(binding.start) + RenderConstants.PIXEL_UV_PIXEL_ADD) * texture.arraySinglePixelFactor
|
||||||
|
@ -25,7 +25,6 @@ data class Vec2Binding(
|
|||||||
val size: Vec2i = glm.abs(start - end)
|
val size: Vec2i = glm.abs(start - end)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun deserialize(json: JsonElement): Vec2Binding {
|
fun deserialize(json: JsonElement): Vec2Binding {
|
||||||
check(json is JsonObject)
|
check(json is JsonObject)
|
||||||
|
|
||||||
|
@ -1,146 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.elements.input
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.config.key.KeyCodes
|
|
||||||
import de.bixilon.minosoft.data.text.ChatComponent
|
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
|
||||||
import de.bixilon.minosoft.util.MMath
|
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
|
|
||||||
|
|
||||||
open class TextField(
|
|
||||||
renderWindow: RenderWindow,
|
|
||||||
val properties: TextFieldProperties,
|
|
||||||
sizing: NodeSizing = NodeSizing(),
|
|
||||||
) : AbsoluteLayout(renderWindow, sizing = sizing), KeyConsumer, MouseConsumer {
|
|
||||||
private var textBuilder: StringBuilder = StringBuilder(properties.defaultText)
|
|
||||||
val textElement = LabelNode(renderWindow, sizing = sizing.copy(), text = ChatComponent.of(text))
|
|
||||||
private var position = text.length
|
|
||||||
|
|
||||||
var text: String
|
|
||||||
get() = textBuilder.toString()
|
|
||||||
set(value) {
|
|
||||||
position = value.length
|
|
||||||
textBuilder = StringBuilder(value)
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
addChild(Vec2i(0, 0), textElement)
|
|
||||||
clearChildrenCache()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clearText() {
|
|
||||||
textBuilder.clear()
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun update() {
|
|
||||||
textElement.text = ChatComponent.of(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun keyInput(keyCodes: KeyCodes) {
|
|
||||||
when (keyCodes) {
|
|
||||||
KeyCodes.KEY_BACKSPACE -> {
|
|
||||||
if (textBuilder.isEmpty() || position == 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
textBuilder.deleteCharAt(--position)
|
|
||||||
}
|
|
||||||
KeyCodes.KEY_DELETE -> {
|
|
||||||
if (textBuilder.isEmpty() || position == textBuilder.length) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
textBuilder.deleteCharAt(position)
|
|
||||||
}
|
|
||||||
KeyCodes.KEY_ENTER -> {
|
|
||||||
if (renderWindow.inputHandler.isKeyDown(KeyCodes.KEY_LEFT_CONTROL, KeyCodes.KEY_RIGHT_CONTROL, KeyCodes.KEY_LEFT_SHIFT, KeyCodes.KEY_RIGHT_SHIFT)) {
|
|
||||||
// new line
|
|
||||||
if (position > properties.maxLength) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
textBuilder.insert(position++, '\n')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
properties.onSubmit(text)
|
|
||||||
if (properties.submitCloses) {
|
|
||||||
properties.onClose()
|
|
||||||
}
|
|
||||||
text = properties.defaultText
|
|
||||||
}
|
|
||||||
KeyCodes.KEY_LEFT -> {
|
|
||||||
position = MMath.clamp(position - 1, 0, text.length)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
KeyCodes.KEY_RIGHT -> {
|
|
||||||
position = MMath.clamp(position + 1, 0, text.length)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
KeyCodes.KEY_V -> {
|
|
||||||
if (renderWindow.inputHandler.isKeyDown(KeyCodes.KEY_LEFT_CONTROL, KeyCodes.KEY_RIGHT_CONTROL)) {
|
|
||||||
// paste
|
|
||||||
textInput(renderWindow.getClipboardText())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ToDo: Up and down for line breaks, shift and ctrl modifier, ...
|
|
||||||
else -> {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
update()
|
|
||||||
super.keyInput(keyCodes)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tick(tick: Long) {
|
|
||||||
if ((tick / FIELD_CURSOR_BLINK_INTERVAL) % 2L == 0L && position == text.length) {
|
|
||||||
textElement.sText = "$textBuilder" + "_"
|
|
||||||
} else {
|
|
||||||
textElement.sText = textBuilder.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun close() {
|
|
||||||
properties.onClose()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun charInput(char: Char) {
|
|
||||||
if (position >= properties.maxLength) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val previous = textBuilder.toString()
|
|
||||||
textBuilder.insert(position++, char.toString())
|
|
||||||
properties.onInput(previous, textBuilder.toString())
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun textInput(text: String) {
|
|
||||||
if (position >= properties.maxLength) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val length = MMath.clamp(text.length, 0, properties.maxLength - position)
|
|
||||||
val previous = textBuilder.toString()
|
|
||||||
textBuilder.insert(position, text.substring(0, length))
|
|
||||||
position += length
|
|
||||||
properties.onInput(previous, textBuilder.toString())
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val FIELD_CURSOR_BLINK_INTERVAL = 8
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.elements.input
|
|
||||||
|
|
||||||
data class TextFieldProperties(
|
|
||||||
var defaultText: String = "",
|
|
||||||
var maxLength: Int = 256,
|
|
||||||
var onSubmit: (text: String) -> Unit = {},
|
|
||||||
var onClose: () -> Unit = {},
|
|
||||||
var onInput: (previousText: String, nextText: String) -> Unit = { _, _ -> },
|
|
||||||
var submitCloses: Boolean = false,
|
|
||||||
)
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.elements.other
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
|
||||||
import de.bixilon.minosoft.data.text.ChatColors
|
|
||||||
import de.bixilon.minosoft.data.text.TextComponent
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderBuilder
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
|
|
||||||
import glm_.vec2.Vec2
|
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
|
|
||||||
class BreakProgressHUDElement(
|
|
||||||
hudRenderer: HUDRenderer,
|
|
||||||
) : HUDElement(hudRenderer) {
|
|
||||||
override val layout = AbsoluteLayout(hudRenderer.renderWindow)
|
|
||||||
|
|
||||||
private val text: LabelNode = LabelNode(hudRenderer.renderWindow)
|
|
||||||
|
|
||||||
override fun init() {
|
|
||||||
layout.addChild(Vec2i(0, 0), text)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun draw() {
|
|
||||||
val currentProgress = hudRenderer.renderWindow.inputHandler.leftClickHandler.breakProgress
|
|
||||||
if (currentProgress in 0.0..1.0) {
|
|
||||||
val textComponent = TextComponent("${(currentProgress * 100).toInt()}%")
|
|
||||||
textComponent.color(when {
|
|
||||||
currentProgress < 0.3 -> ChatColors.RED
|
|
||||||
currentProgress < 0.7 -> ChatColors.YELLOW
|
|
||||||
else -> ChatColors.GREEN
|
|
||||||
})
|
|
||||||
text.text = textComponent
|
|
||||||
} else {
|
|
||||||
// Toggle visibility?
|
|
||||||
text.sText = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object : HUDRenderBuilder<BreakProgressHUDElement> {
|
|
||||||
override val RESOURCE_LOCATION = ResourceLocation("minosoft:break_progress")
|
|
||||||
override val DEFAULT_PROPERTIES = HUDElementProperties(
|
|
||||||
position = Vec2(0.08f, 0.0f),
|
|
||||||
xBinding = HUDElementProperties.PositionBindings.CENTER,
|
|
||||||
yBinding = HUDElementProperties.PositionBindings.CENTER,
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun build(hudRenderer: HUDRenderer): BreakProgressHUDElement {
|
|
||||||
return BreakProgressHUDElement(hudRenderer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.elements.other
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderBuilder
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.ImageNode
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
|
||||||
import glm_.vec2.Vec2
|
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
|
|
||||||
class CrosshairHUDElement(
|
|
||||||
hudRenderer: HUDRenderer,
|
|
||||||
) : HUDElement(hudRenderer) {
|
|
||||||
override val layout = AbsoluteLayout(hudRenderer.renderWindow)
|
|
||||||
private lateinit var crosshairImage: ImageNode
|
|
||||||
|
|
||||||
override fun init() {
|
|
||||||
val atlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:crosshair")]!!
|
|
||||||
crosshairImage = ImageNode(hudRenderer.renderWindow, NodeSizing(minSize = atlasElement.binding.size), textureLike = atlasElement)
|
|
||||||
layout.addChild(Vec2i(0, 0), crosshairImage)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object : HUDRenderBuilder<CrosshairHUDElement> {
|
|
||||||
override val RESOURCE_LOCATION = ResourceLocation("minosoft:crosshair")
|
|
||||||
override val DEFAULT_PROPERTIES = HUDElementProperties(
|
|
||||||
position = Vec2(0.0f, 0.0f),
|
|
||||||
xBinding = HUDElementProperties.PositionBindings.CENTER,
|
|
||||||
yBinding = HUDElementProperties.PositionBindings.CENTER,
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun build(hudRenderer: HUDRenderer): CrosshairHUDElement {
|
|
||||||
return CrosshairHUDElement(hudRenderer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.chat
|
|
||||||
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
|
|
||||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderBuilder
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.elements.input.TextField
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.elements.input.TextFieldProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
|
|
||||||
import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
|
|
||||||
import de.bixilon.minosoft.modding.event.CallbackEventInvoker
|
|
||||||
import glm_.vec2.Vec2
|
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
|
|
||||||
class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer) {
|
|
||||||
override val layout = AbsoluteLayout(hudRenderer.renderWindow)
|
|
||||||
private lateinit var inputField: TextField
|
|
||||||
|
|
||||||
override fun init() {
|
|
||||||
inputField = TextField(
|
|
||||||
renderWindow = hudRenderer.renderWindow,
|
|
||||||
properties = TextFieldProperties(
|
|
||||||
maxLength = 256,
|
|
||||||
submitCloses = true,
|
|
||||||
onSubmit = { hudRenderer.renderWindow.connection.sender.sendChatMessage(it) },
|
|
||||||
onClose = { closeChat() },
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
layout.addChild(Vec2i(0, 0), inputField)
|
|
||||||
inputField.apply()
|
|
||||||
|
|
||||||
hudRenderer.renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) {
|
|
||||||
openChat()
|
|
||||||
}
|
|
||||||
hudRenderer.connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> {
|
|
||||||
layout.sizing.minSize.x = it.screenDimensions.x
|
|
||||||
layout.sizing.maxSize.x = it.screenDimensions.x
|
|
||||||
inputField.textElement.setProperties.hardWrap = (inputField.textElement.sizing.minSize.x / scale).toInt()
|
|
||||||
layout.apply()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun openChat() {
|
|
||||||
hudRenderer.renderWindow.inputHandler.currentKeyConsumer = inputField
|
|
||||||
}
|
|
||||||
|
|
||||||
fun closeChat() {
|
|
||||||
hudRenderer.renderWindow.inputHandler.currentKeyConsumer = null
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object : HUDRenderBuilder<ChatBoxHUDElement> {
|
|
||||||
override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("minosoft:chat")
|
|
||||||
override val DEFAULT_PROPERTIES = HUDElementProperties(
|
|
||||||
position = Vec2(0.0f, -1.0f),
|
|
||||||
xBinding = HUDElementProperties.PositionBindings.CENTER,
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun build(hudRenderer: HUDRenderer): ChatBoxHUDElement {
|
|
||||||
return ChatBoxHUDElement(hudRenderer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.debug
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.text.ChatComponent
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.RowLayout
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
|
|
||||||
|
|
||||||
abstract class DebugScreenNode(hudRenderer: HUDRenderer) : HUDElement(hudRenderer) {
|
|
||||||
override val layout = RowLayout(hudRenderer.renderWindow)
|
|
||||||
protected var lastPrepareTime = 0L
|
|
||||||
|
|
||||||
fun text(text: String = ""): LabelNode {
|
|
||||||
val textElement = LabelNode(hudRenderer.renderWindow, text = ChatComponent.of(text))
|
|
||||||
layout.addRow(textElement)
|
|
||||||
return textElement
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,141 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.debug
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
|
|
||||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderBuilder
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeAlignment
|
|
||||||
import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
|
|
||||||
import de.bixilon.minosoft.modding.event.CallbackEventInvoker
|
|
||||||
import de.bixilon.minosoft.modding.loading.ModLoader
|
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
|
||||||
import de.bixilon.minosoft.util.GitInfo
|
|
||||||
import de.bixilon.minosoft.util.SystemInformation
|
|
||||||
import de.bixilon.minosoft.util.UnitFormatter
|
|
||||||
import glm_.vec2.Vec2
|
|
||||||
import org.lwjgl.opengl.GL11.*
|
|
||||||
|
|
||||||
|
|
||||||
class HUDSystemDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer) {
|
|
||||||
|
|
||||||
init {
|
|
||||||
layout.sizing.forceAlign = NodeAlignment.RIGHT
|
|
||||||
layout.sizing.padding.top = 2
|
|
||||||
layout.sizing.padding.right = 2
|
|
||||||
text("Java: ${Runtime.version()} ${System.getProperty("sun.arch.data.model")}bit")
|
|
||||||
}
|
|
||||||
|
|
||||||
private val memoryText = text("TBA")
|
|
||||||
private val allocatedMemoryText = text("TBA")
|
|
||||||
|
|
||||||
init {
|
|
||||||
text("System: ${SystemInformation.SYSTEM_MEMORY_TEXT}")
|
|
||||||
text()
|
|
||||||
text("OS: ${SystemInformation.OS_TEXT}")
|
|
||||||
text("CPU: ${SystemInformation.PROCESSOR_TEXT}")
|
|
||||||
text()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val displayText = text("TBA")
|
|
||||||
private val gpuText = text("TBA")
|
|
||||||
private val gpuVersionText = text("TBA")
|
|
||||||
|
|
||||||
|
|
||||||
init {
|
|
||||||
text()
|
|
||||||
text(
|
|
||||||
if (GitInfo.IS_INITIALIZED) {
|
|
||||||
"Commit: ${GitInfo.GIT_COMMIT_ID_DESCRIBE}: ${GitInfo.GIT_COMMIT_MESSAGE_SHORT}"
|
|
||||||
} else {
|
|
||||||
"GitInfo uninitialized :("
|
|
||||||
})
|
|
||||||
text()
|
|
||||||
text("Mods: ${ModLoader.MOD_MAP.size} active, ${hudRenderer.connection.eventListenerSize} listeners")
|
|
||||||
}
|
|
||||||
|
|
||||||
private val targetPosition = text("TBA")
|
|
||||||
private val targetBlockState = text("TBA")
|
|
||||||
|
|
||||||
override fun init() {
|
|
||||||
gpuText.sText = "GPU: " + (glGetString(GL_RENDERER) ?: "unknown")
|
|
||||||
gpuVersionText.sText = "Version: " + (glGetString(GL_VERSION) ?: "unknown")
|
|
||||||
|
|
||||||
hudRenderer.connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> {
|
|
||||||
displayText.sText = "Display: ${getScreenDimensions()}"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun draw() {
|
|
||||||
if (System.currentTimeMillis() - lastPrepareTime < ProtocolDefinition.TICK_TIME * 2) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
memoryText.sText = "Memory: ${getUsedMemoryPercent()}% ${getFormattedUsedMemory()}/${SystemInformation.MAX_MEMORY_TEXT}"
|
|
||||||
allocatedMemoryText.sText = "Allocated: ${getAllocatedMemoryPercent()}% ${getFormattedAllocatedMemory()}"
|
|
||||||
|
|
||||||
val rayCastHit = hudRenderer.renderWindow.inputHandler.camera.getTargetBlock()
|
|
||||||
if (rayCastHit == null) {
|
|
||||||
targetPosition.sText = ""
|
|
||||||
targetBlockState.sText = ""
|
|
||||||
} else {
|
|
||||||
targetPosition.sText = "Target block: ${rayCastHit.blockPosition}"
|
|
||||||
targetBlockState.sText = rayCastHit.blockState.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
lastPrepareTime = System.currentTimeMillis()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getUsedMemory(): Long {
|
|
||||||
return SystemInformation.RUNTIME.totalMemory() - SystemInformation.RUNTIME.freeMemory()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getFormattedUsedMemory(): String {
|
|
||||||
return UnitFormatter.formatBytes(getUsedMemory())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAllocatedMemory(): Long {
|
|
||||||
return SystemInformation.RUNTIME.totalMemory()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getFormattedAllocatedMemory(): String {
|
|
||||||
return UnitFormatter.formatBytes(getAllocatedMemory())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getUsedMemoryPercent(): Long {
|
|
||||||
return getUsedMemory() * 100 / SystemInformation.RUNTIME.maxMemory()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAllocatedMemoryPercent(): Long {
|
|
||||||
return getAllocatedMemory() * 100 / SystemInformation.RUNTIME.maxMemory()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getScreenDimensions(): String {
|
|
||||||
return "${hudRenderer.renderWindow.screenDimensions.x}x${hudRenderer.renderWindow.screenDimensions.y}"
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object : HUDRenderBuilder<HUDSystemDebugNode> {
|
|
||||||
override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("minosoft:system_debug_screen")
|
|
||||||
override val DEFAULT_PROPERTIES = HUDElementProperties(
|
|
||||||
position = Vec2(1.0f, 1.0f),
|
|
||||||
toggleKeyBinding = KeyBindingsNames.TOGGLE_DEBUG_SCREEN,
|
|
||||||
enabled = false,
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun build(hudRenderer: HUDRenderer): HUDSystemDebugNode {
|
|
||||||
return HUDSystemDebugNode(hudRenderer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,163 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.debug
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
|
|
||||||
import de.bixilon.minosoft.data.Directions
|
|
||||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
|
||||||
import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderBuilder
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeAlignment
|
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
|
||||||
import de.bixilon.minosoft.util.UnitFormatter
|
|
||||||
import glm_.vec2.Vec2
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
class HUDWorldDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer) {
|
|
||||||
private val camera = hudRenderer.renderWindow.inputHandler.camera
|
|
||||||
private val worldRenderer = hudRenderer.renderWindow.rendererMap[WorldRenderer.RESOURCE_LOCATION] as WorldRenderer?
|
|
||||||
|
|
||||||
init {
|
|
||||||
layout.sizing.forceAlign = NodeAlignment.LEFT
|
|
||||||
layout.sizing.padding.left = 2
|
|
||||||
layout.sizing.padding.top = 2
|
|
||||||
text("§cMinosoft 0.1-pre1")
|
|
||||||
}
|
|
||||||
|
|
||||||
private val fpsText = text("TBA")
|
|
||||||
private val timingsText = text("TBA")
|
|
||||||
private val chunksText = text("TBA")
|
|
||||||
private val openGLText = text("TBA")
|
|
||||||
|
|
||||||
init {
|
|
||||||
text("Connected to ${hudRenderer.connection.address} on ${hudRenderer.connection.version} with ${hudRenderer.connection.account.username}")
|
|
||||||
text("")
|
|
||||||
}
|
|
||||||
|
|
||||||
private val positionText = text("TBA")
|
|
||||||
private val blockPositionText = text("TBA")
|
|
||||||
private val chunkPositionText = text("TBA")
|
|
||||||
private val facingText = text("TBA")
|
|
||||||
private val gamemodeText = text("TBA")
|
|
||||||
private val dimensionText = text("TBA")
|
|
||||||
private val biomeText = text("TBA")
|
|
||||||
|
|
||||||
init {
|
|
||||||
text()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val difficultyText = text("TBA")
|
|
||||||
private val lightText = text("TBA")
|
|
||||||
|
|
||||||
|
|
||||||
override fun draw() {
|
|
||||||
if (System.currentTimeMillis() - lastPrepareTime < ProtocolDefinition.TICK_TIME * 2) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fpsText.sText = "FPS: ${getFPS()}"
|
|
||||||
chunksText.sText = "Chunks: q=${worldRenderer?.queuedChunks?.size} v=${worldRenderer?.visibleChunks?.size} p=${worldRenderer?.allChunkSections?.size} t=${hudRenderer.connection.world.chunks.size}"
|
|
||||||
timingsText.sText = "Timings: avg ${getAvgFrameTime()}ms, min ${getMinFrameTime()}ms, max ${getMaxFrameTime()}ms"
|
|
||||||
openGLText.sText = "GL: m=${worldRenderer?.meshes?.let { UnitFormatter.formatNumber(it) }} t=${worldRenderer?.triangles?.let { UnitFormatter.formatNumber(it) }}"
|
|
||||||
|
|
||||||
|
|
||||||
// ToDo: Prepare on change
|
|
||||||
gamemodeText.sText = "Gamemode: ${hudRenderer.connection.player.entity.gamemode.name.lowercase(Locale.getDefault())}"
|
|
||||||
positionText.sText = "XYZ ${getPosition()}"
|
|
||||||
blockPositionText.sText = "Block ${getBlockPosition()}"
|
|
||||||
chunkPositionText.sText = "Chunk ${getChunkLocation()}"
|
|
||||||
facingText.sText = "Facing: ${getFacing()}"
|
|
||||||
|
|
||||||
biomeText.sText = "Biome: ${camera.currentBiome}"
|
|
||||||
dimensionText.sText = "Dimension: ${hudRenderer.connection.world.dimension}"
|
|
||||||
|
|
||||||
difficultyText.sText = "Difficulty: ${hudRenderer.connection.world.difficulty?.name?.lowercase(Locale.getDefault())}, ${
|
|
||||||
if (hudRenderer.connection.world.difficultyLocked) {
|
|
||||||
"locked"
|
|
||||||
} else {
|
|
||||||
"unlocked"
|
|
||||||
}
|
|
||||||
}"
|
|
||||||
|
|
||||||
lightText.sText = "Client light: sky=${hudRenderer.connection.world.worldLightAccessor.getSkyLight(camera.blockPosition)}, block=${hudRenderer.connection.world.worldLightAccessor.getBlockLight(camera.blockPosition)}"
|
|
||||||
|
|
||||||
|
|
||||||
lastPrepareTime = System.currentTimeMillis()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun nanoToMillis1d(nanos: Long): String {
|
|
||||||
return "%.1f".format(nanos / 1E6f)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getFPS(): String {
|
|
||||||
val renderStats = hudRenderer.renderWindow.renderStats
|
|
||||||
return "${renderStats.fpsLastSecond}"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAvgFrameTime(): String {
|
|
||||||
return nanoToMillis1d(hudRenderer.renderWindow.renderStats.avgFrameTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getMinFrameTime(): String {
|
|
||||||
return nanoToMillis1d(hudRenderer.renderWindow.renderStats.minFrameTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getMaxFrameTime(): String {
|
|
||||||
return nanoToMillis1d(hudRenderer.renderWindow.renderStats.maxFrameTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun getPosition(): String {
|
|
||||||
return "${formatCoordinate(camera.playerEntity.position.x)} / ${formatCoordinate(camera.playerEntity.position.y)} / ${formatCoordinate(camera.playerEntity.position.z)}"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getBlockPosition(): String {
|
|
||||||
return "${camera.blockPosition.x} / ${camera.blockPosition.y} / ${camera.blockPosition.z}"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getChunkLocation(): String {
|
|
||||||
return "${camera.inChunkSectionPosition.x} ${camera.inChunkSectionPosition.y} ${camera.inChunkSectionPosition.z} in ${camera.chunkPosition.x} ${camera.sectionHeight} ${camera.chunkPosition.y}"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getFacing(): String {
|
|
||||||
val yaw = hudRenderer.renderWindow.inputHandler.camera.playerEntity.rotation.yaw
|
|
||||||
val pitch = hudRenderer.renderWindow.inputHandler.camera.playerEntity.rotation.pitch
|
|
||||||
val direction = Directions.byDirection(camera.cameraFront)
|
|
||||||
return "${Directions.byDirection(camera.cameraFront).name.lowercase(Locale.getDefault())} ${direction.directionVector} (${formatRotation(yaw.toDouble())} / ${formatRotation(pitch.toDouble())})"
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object : HUDRenderBuilder<HUDWorldDebugNode> {
|
|
||||||
override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("minosoft:world_debug_screen")
|
|
||||||
override val DEFAULT_PROPERTIES = HUDElementProperties(
|
|
||||||
position = Vec2(-1.0f, 1.0f),
|
|
||||||
toggleKeyBinding = KeyBindingsNames.TOGGLE_DEBUG_SCREEN,
|
|
||||||
enabled = false,
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun build(hudRenderer: HUDRenderer): HUDWorldDebugNode {
|
|
||||||
return HUDWorldDebugNode(hudRenderer)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun formatCoordinate(coordinate: Float): String {
|
|
||||||
return "%.3f".format(coordinate)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun formatRotation(rotation: Double): String {
|
|
||||||
return "%.1f".format(rotation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,139 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.layout
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.Node
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeAlignment
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
|
||||||
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
|
|
||||||
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
|
|
||||||
import de.bixilon.minosoft.util.MMath
|
|
||||||
import glm_.mat4x4.Mat4
|
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
|
|
||||||
open class AbsoluteLayout(
|
|
||||||
renderWindow: RenderWindow,
|
|
||||||
sizing: NodeSizing = NodeSizing(),
|
|
||||||
initialCacheSize: Int = DEFAULT_INITIAL_CACHE_SIZE,
|
|
||||||
) : Layout(renderWindow, sizing, initialCacheSize) {
|
|
||||||
private val children: MutableMap<Node, Vec2i> = synchronizedMapOf()
|
|
||||||
|
|
||||||
override fun clearChildren() {
|
|
||||||
children.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addChild(start: Vec2i, child: Node) {
|
|
||||||
child.parent = this
|
|
||||||
child.apply()
|
|
||||||
if (children.isEmpty()) {
|
|
||||||
start.x += child.sizing.margin.left + sizing.padding.left
|
|
||||||
start.y += child.sizing.margin.top + sizing.padding.top
|
|
||||||
}
|
|
||||||
children[child] = start
|
|
||||||
apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun recursiveApply() {
|
|
||||||
for ((child, _) in children.toSynchronizedMap()) {
|
|
||||||
if (child is AbsoluteLayout) {
|
|
||||||
child.recursiveApply()
|
|
||||||
} else {
|
|
||||||
child.apply()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun checkAlignment() {
|
|
||||||
when (sizing.forceAlign) {
|
|
||||||
NodeAlignment.RIGHT -> {
|
|
||||||
for ((child, start) in children.toSynchronizedMap()) {
|
|
||||||
start.x = sizing.currentSize.x - (child.sizing.margin.right + sizing.padding.right + child.sizing.currentSize.x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NodeAlignment.LEFT -> {
|
|
||||||
for ((child, start) in children.toSynchronizedMap()) {
|
|
||||||
start.x = child.sizing.margin.left + sizing.padding.left
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NodeAlignment.CENTER -> {
|
|
||||||
for ((child, start) in children.toSynchronizedMap()) {
|
|
||||||
start.x = (sizing.currentSize.x - child.sizing.currentSize.x) / 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply() {
|
|
||||||
sizing.validate()
|
|
||||||
clearCache()
|
|
||||||
recalculateSize()
|
|
||||||
checkAlignment()
|
|
||||||
parent?.apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun recalculateSize() {
|
|
||||||
sizing.currentSize = Vec2i(sizing.minSize)
|
|
||||||
for ((childNode, start) in children.toSynchronizedMap()) {
|
|
||||||
checkSize(childNode, start)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clearCache() {
|
|
||||||
cache.clear()
|
|
||||||
parent?.clearCache()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkSize(child: Node, start: Vec2i) {
|
|
||||||
var changed = false
|
|
||||||
val end = start + child.sizing.currentSize
|
|
||||||
if (end.x > sizing.currentSize.x) {
|
|
||||||
sizing.currentSize.x = MMath.clamp(end.x, sizing.minSize.x, sizing.maxSize.x)
|
|
||||||
changed = true
|
|
||||||
}
|
|
||||||
if (end.y > sizing.currentSize.y) {
|
|
||||||
sizing.currentSize.y = MMath.clamp(end.y, sizing.minSize.y, sizing.maxSize.y)
|
|
||||||
changed = true
|
|
||||||
}
|
|
||||||
if (changed) {
|
|
||||||
clearCache()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addToStart(start: Vec2i, elementPosition: Vec2i): Vec2i {
|
|
||||||
return Vec2i(start.x + elementPosition.x, start.y - elementPosition.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareCache(start: Vec2i, scaleFactor: Float, matrix: Mat4, z: Int) {
|
|
||||||
for ((child, childStart) in children.toSynchronizedMap()) {
|
|
||||||
child.checkCache(addToStart(start, childStart * scaleFactor), scaleFactor, matrix, z)
|
|
||||||
cache.addCache(child.cache)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clearChildrenCache() {
|
|
||||||
for ((child, _) in children.toSynchronizedMap()) {
|
|
||||||
if (child is AbsoluteLayout) {
|
|
||||||
child.clearChildrenCache()
|
|
||||||
} else {
|
|
||||||
child.clearCache()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clearCache()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun removeChild(node: Node) {
|
|
||||||
children.remove(node)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.layout
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.Node
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
|
||||||
|
|
||||||
abstract class Layout(
|
|
||||||
renderWindow: RenderWindow,
|
|
||||||
sizing: NodeSizing = NodeSizing(),
|
|
||||||
initialCacheSize: Int = DEFAULT_INITIAL_CACHE_SIZE,
|
|
||||||
) : Node(renderWindow, sizing, initialCacheSize) {
|
|
||||||
|
|
||||||
abstract fun clearChildren()
|
|
||||||
|
|
||||||
abstract fun recursiveApply()
|
|
||||||
|
|
||||||
abstract fun checkAlignment()
|
|
||||||
|
|
||||||
abstract fun recalculateSize()
|
|
||||||
|
|
||||||
abstract fun clearChildrenCache()
|
|
||||||
|
|
||||||
abstract fun removeChild(node: Node)
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.layout
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.Node
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
|
|
||||||
class RowLayout(
|
|
||||||
renderWindow: RenderWindow,
|
|
||||||
sizing: NodeSizing = NodeSizing(),
|
|
||||||
initialCacheSize: Int = DEFAULT_INITIAL_CACHE_SIZE,
|
|
||||||
) : AbsoluteLayout(renderWindow, sizing, initialCacheSize) {
|
|
||||||
|
|
||||||
fun addRow(node: Node) {
|
|
||||||
addChild(Vec2i(0, sizing.currentSize.y + node.sizing.margin.top + node.sizing.padding.top), node)
|
|
||||||
apply()
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,22 +11,32 @@
|
|||||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.hud.nodes
|
package de.bixilon.minosoft.gui.rendering.hud.nodes.primitive
|
||||||
|
|
||||||
import de.bixilon.minosoft.Minosoft
|
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
|
import de.bixilon.minosoft.data.text.RGBColor
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.Layout
|
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(protected val hudRenderer: HUDRenderer) {
|
abstract class HUDElement(
|
||||||
abstract val layout: Layout
|
val position: HUDElementVec2,
|
||||||
|
val positionAnchor: HUDElementPositionAnchors,
|
||||||
|
val content: ResourceLocation,
|
||||||
|
val size: HUDElementVec2,
|
||||||
|
val realZ: Float,
|
||||||
|
val tint: RGBColor,
|
||||||
|
) {
|
||||||
|
lateinit var hudRenderer: HUDRenderer
|
||||||
|
|
||||||
lateinit var properties: HUDElementProperties
|
open fun init(hudRenderer: HUDRenderer) {
|
||||||
|
this.hudRenderer = hudRenderer
|
||||||
|
}
|
||||||
|
|
||||||
val scale: Float
|
|
||||||
get() = properties.scale * Minosoft.getConfig().config.game.hud.scale
|
|
||||||
|
|
||||||
open fun init() {}
|
|
||||||
open fun postInit() {}
|
open fun postInit() {}
|
||||||
|
|
||||||
open fun draw() {}
|
open fun draw() {}
|
||||||
|
|
||||||
|
open fun prepare(matrix: Mat4) {}
|
||||||
}
|
}
|
@ -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!
|
||||||
|
)
|
||||||
|
}
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.text.RGBColor
|
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLike
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
|
||||||
import de.bixilon.minosoft.gui.rendering.util.mesh.SimpleTextureMesh
|
|
||||||
import glm_.mat4x4.Mat4
|
|
||||||
import glm_.vec2.Vec2
|
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
import glm_.vec3.Vec3
|
|
||||||
import glm_.vec4.Vec4
|
|
||||||
|
|
||||||
class ImageNode(
|
|
||||||
renderWindow: RenderWindow,
|
|
||||||
sizing: NodeSizing = NodeSizing(),
|
|
||||||
var textureLike: TextureLike?,
|
|
||||||
val z: Int = 0,
|
|
||||||
val tintColor: RGBColor? = null,
|
|
||||||
) : Node(renderWindow, sizing = sizing, initialCacheSize = SimpleTextureMesh.SimpleTextureMeshStruct.FLOATS_PER_VERTEX * 6) {
|
|
||||||
|
|
||||||
private fun addToStart(start: Vec2i, elementPosition: Vec2i): Vec2i {
|
|
||||||
return Vec2i(start.x + elementPosition.x, start.y - elementPosition.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addToEnd(start: Vec2i, elementPosition: Vec2i): Vec2i {
|
|
||||||
return Vec2i(start.x + elementPosition.x, start.y - elementPosition.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply() {}
|
|
||||||
|
|
||||||
override fun prepareCache(start: Vec2i, scaleFactor: Float, matrix: Mat4, z: Int) {
|
|
||||||
val modelStart = matrix * Vec4(RenderConstants.PIXEL_UV_PIXEL_ADD + start, 1.0f, 1.0f)
|
|
||||||
val ourEnd = addToEnd(start, sizing.currentSize * scaleFactor)
|
|
||||||
val modelEnd = matrix * Vec4(RenderConstants.PIXEL_UV_PIXEL_ADD + ourEnd, 1.0f, 1.0f)
|
|
||||||
|
|
||||||
val uvStart = textureLike?.uvStart ?: Vec2()
|
|
||||||
val uvEnd = textureLike?.uvEnd ?: Vec2()
|
|
||||||
|
|
||||||
val realZ = RenderConstants.HUD_Z_COORDINATE + RenderConstants.HUD_Z_COORDINATE_Z_FACTOR * (this.z + z)
|
|
||||||
|
|
||||||
fun addVertex(positionX: Float, positionY: Float, textureUV: Vec2) {
|
|
||||||
cache.addVertex(Vec3(positionX, positionY, realZ), textureUV, textureLike?.texture, tintColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
addVertex(modelStart.x, modelStart.y, Vec2(uvStart.x, uvStart.y))
|
|
||||||
addVertex(modelStart.x, modelEnd.y, Vec2(uvStart.x, uvEnd.y))
|
|
||||||
addVertex(modelEnd.x, modelStart.y, Vec2(uvEnd.x, uvStart.y))
|
|
||||||
addVertex(modelStart.x, modelEnd.y, Vec2(uvStart.x, uvEnd.y))
|
|
||||||
addVertex(modelEnd.x, modelEnd.y, Vec2(uvEnd.x, uvEnd.y))
|
|
||||||
addVertex(modelEnd.x, modelStart.y, Vec2(uvEnd.x, uvStart.y))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.text.ChatComponent
|
|
||||||
import de.bixilon.minosoft.data.text.RGBColor
|
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
|
||||||
import de.bixilon.minosoft.gui.rendering.font.Font
|
|
||||||
import de.bixilon.minosoft.gui.rendering.font.text.TextGetProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.font.text.TextSetProperties
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
|
|
||||||
class LabelNode(
|
|
||||||
renderWindow: RenderWindow,
|
|
||||||
sizing: NodeSizing = NodeSizing(minSize = Vec2i(0, Font.CHAR_HEIGHT + 2 * TEXT_BACKGROUND_OFFSET)),
|
|
||||||
text: ChatComponent = ChatComponent.of(""),
|
|
||||||
var background: Boolean = true,
|
|
||||||
val setProperties: TextSetProperties = TextSetProperties(),
|
|
||||||
) : AbsoluteLayout(renderWindow, sizing) {
|
|
||||||
var getProperties = TextGetProperties()
|
|
||||||
private set
|
|
||||||
|
|
||||||
var text: ChatComponent = text
|
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
prepare()
|
|
||||||
}
|
|
||||||
|
|
||||||
var sText: String
|
|
||||||
get() = text.message
|
|
||||||
set(value) {
|
|
||||||
text = ChatComponent.of(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
prepare()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepare() {
|
|
||||||
clearChildren()
|
|
||||||
getProperties = TextGetProperties()
|
|
||||||
val textStartPosition = Vec2i(TEXT_BACKGROUND_OFFSET, TEXT_BACKGROUND_OFFSET)
|
|
||||||
text.prepareRender(textStartPosition, Vec2i(), renderWindow, this, 1, setProperties, getProperties)
|
|
||||||
|
|
||||||
if (background && text.message.isNotBlank()) {
|
|
||||||
drawBackground(getProperties.size + textStartPosition + TEXT_BACKGROUND_OFFSET)
|
|
||||||
}
|
|
||||||
apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun drawBackground(end: Vec2i, z: Int = 1, tintColor: RGBColor = RenderConstants.TEXT_BACKGROUND_COLOR) {
|
|
||||||
addChild(Vec2i(0, 0), ImageNode(renderWindow, NodeSizing(minSize = end), renderWindow.WHITE_TEXTURE, 0, tintColor))
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val TEXT_BACKGROUND_OFFSET = 1
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.gui.rendering.RenderWindow
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.HUDCacheMesh
|
|
||||||
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
|
|
||||||
import glm_.mat4x4.Mat4
|
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
|
|
||||||
abstract class Node(
|
|
||||||
val renderWindow: RenderWindow,
|
|
||||||
val sizing: NodeSizing = NodeSizing(),
|
|
||||||
initialCacheSize: Int = DEFAULT_INITIAL_CACHE_SIZE,
|
|
||||||
) {
|
|
||||||
val cache = HUDCacheMesh(initialCacheSize)
|
|
||||||
open var parent: Node? = null
|
|
||||||
|
|
||||||
abstract fun apply()
|
|
||||||
|
|
||||||
fun needsCacheUpdate(): Boolean {
|
|
||||||
return cache.isEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun checkCache(start: Vec2i, scaleFactor: Float, matrix: Mat4, z: Int = 1) {
|
|
||||||
if (!needsCacheUpdate()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
prepareCache(start, scaleFactor, matrix, z)
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun clearCache() {
|
|
||||||
cache.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun prepareCache(start: Vec2i, scaleFactor: Float, matrix: Mat4, z: Int = 1)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val DEFAULT_INITIAL_CACHE_SIZE = 1000
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.properties
|
|
||||||
|
|
||||||
enum class NodeAlignment {
|
|
||||||
LEFT,
|
|
||||||
RIGHT,
|
|
||||||
CENTER,
|
|
||||||
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.properties
|
|
||||||
|
|
||||||
import de.bixilon.minosoft.util.MMath
|
|
||||||
import glm_.vec2.Vec2i
|
|
||||||
|
|
||||||
data class NodeSizing(
|
|
||||||
var minSize: Vec2i = Vec2i(0, 0),
|
|
||||||
var maxSize: Vec2i = Vec2i(Int.MAX_VALUE, Int.MAX_VALUE),
|
|
||||||
var margin: Spacing = Spacing(0, 0, 0, 0),
|
|
||||||
var padding: Spacing = Spacing(0, 0, 0, 0),
|
|
||||||
var forceAlign: NodeAlignment? = null,
|
|
||||||
) {
|
|
||||||
var currentSize: Vec2i = Vec2i(minSize)
|
|
||||||
|
|
||||||
|
|
||||||
fun validate() {
|
|
||||||
MMath.clamp(currentSize, minSize, maxSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
var forceSize: Vec2i
|
|
||||||
get() = currentSize
|
|
||||||
set(value) {
|
|
||||||
minSize = value
|
|
||||||
maxSize = value
|
|
||||||
validate()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.properties
|
|
||||||
|
|
||||||
data class Spacing(
|
|
||||||
var top: Int = 0,
|
|
||||||
var right: Int = 0,
|
|
||||||
var bottom: Int = 0,
|
|
||||||
var left: Int = 0,
|
|
||||||
)
|
|
@ -328,4 +328,20 @@ object VecUtil {
|
|||||||
Axes.Z -> this.z
|
Axes.Z -> this.z
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import com.squareup.moshi.Moshi
|
|||||||
import com.squareup.moshi.Types
|
import com.squareup.moshi.Types
|
||||||
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
||||||
import de.bixilon.minosoft.config.config.Config
|
import de.bixilon.minosoft.config.config.Config
|
||||||
|
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.HUDElementSerializer
|
||||||
import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties
|
import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties
|
||||||
|
|
||||||
object JSONSerializer {
|
object JSONSerializer {
|
||||||
@ -27,6 +28,7 @@ object JSONSerializer {
|
|||||||
.add(AccountSerializer)
|
.add(AccountSerializer)
|
||||||
.add(ServerSerializer)
|
.add(ServerSerializer)
|
||||||
.add(ResourceLocationSerializer)
|
.add(ResourceLocationSerializer)
|
||||||
|
.add(HUDElementSerializer)
|
||||||
.add(KotlinJsonAdapterFactory())
|
.add(KotlinJsonAdapterFactory())
|
||||||
.build()!!
|
.build()!!
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user