rendering rewrite parts of the hud

* Will re-add soon: Hotbar, ChatBox
This commit is contained in:
Bixilon 2021-04-14 00:19:14 +02:00
parent 6dce7a4ecd
commit b33779f71f
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
28 changed files with 338 additions and 870 deletions

View File

@ -15,8 +15,8 @@ package de.bixilon.minosoft.data.text
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.locale.minecraft.Translator
import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.TextElement
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import glm_.vec2.Vec2i
import javafx.collections.ObservableList
@ -174,9 +174,9 @@ class BaseComponent : ChatComponent {
return nodes
}
override fun prepareRender(startPosition: Vec2i, offset: Vec2i, font: Font, textElement: TextElement, z: Int, retMaxSize: Vec2i) {
override fun prepareRender(startPosition: Vec2i, offset: Vec2i, renderWindow: RenderWindow, textElement: LabelNode, z: Int, retMaxSize: Vec2i) {
for (part in parts) {
part.prepareRender(startPosition, offset, font, textElement, z, retMaxSize)
part.prepareRender(startPosition, offset, renderWindow, textElement, z, retMaxSize)
}
}

View File

@ -17,8 +17,8 @@ import com.google.gson.JsonObject
import com.google.gson.JsonParser
import com.google.gson.JsonPrimitive
import de.bixilon.minosoft.data.locale.minecraft.Translator
import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.TextElement
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
import de.bixilon.minosoft.util.nbt.tag.StringTag
import glm_.vec2.Vec2i
import javafx.collections.FXCollections
@ -61,7 +61,7 @@ interface ChatComponent {
/**
* Prepares the chat component for rendering (used in opengl)
*/
fun prepareRender(startPosition: Vec2i, offset: Vec2i, font: Font, textElement: TextElement, z: Int, retMaxSize: Vec2i)
fun prepareRender(startPosition: Vec2i, offset: Vec2i, renderWindow: RenderWindow, textElement: LabelNode, z: Int, retMaxSize: Vec2i)
companion object {

View File

@ -14,12 +14,13 @@ package de.bixilon.minosoft.data.text
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.hud.elements.primitive.ImageElement
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.TextElement
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.util.Util
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
import javafx.animation.Animation
import javafx.animation.KeyFrame
@ -160,7 +161,7 @@ open class TextComponent(
}
override fun prepareRender(startPosition: Vec2i, offset: Vec2i, font: Font, textElement: TextElement, z: Int, retMaxSize: Vec2i) {
override fun prepareRender(startPosition: Vec2i, offset: Vec2i, renderWindow: RenderWindow, textElement: LabelNode, z: Int, retMaxSize: Vec2i) {
val color = this.color ?: ChatColors.WHITE
@ -177,11 +178,11 @@ open class TextComponent(
retMaxSize.y += yOffset
continue
}
val fontChar = font.getChar(char)
val fontChar = renderWindow.font.getChar(char)
val scaledWidth = (fontChar.size.x * (Font.CHAR_HEIGHT / fontChar.height.toFloat())).toInt()
val charStart = startPosition + offset
textElement.batchAdd(ImageElement(charStart, fontChar, charStart + Vec2(scaledWidth, Font.CHAR_HEIGHT), z, color))
textElement.addChild(charStart, ImageNode(renderWindow, NodeSizing(minSize = Vec2i(scaledWidth, Font.CHAR_HEIGHT)), fontChar, 1, color))
// ad spacer between chars
offset.x += scaledWidth + Font.SPACE_BETWEEN_CHARS

View File

@ -24,6 +24,8 @@ import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer
import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLike
import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLikeTexture
import de.bixilon.minosoft.gui.rendering.hud.elements.input.KeyConsumer
import de.bixilon.minosoft.gui.rendering.textures.Texture
import de.bixilon.minosoft.gui.rendering.textures.TextureArray
@ -86,6 +88,8 @@ class RenderWindow(
private var skipNextChatPress = false
lateinit var WHITE_TEXTURE: TextureLike
var currentKeyConsumer: KeyConsumer?
get() = _currentInputConsumer
set(value) {
@ -304,6 +308,13 @@ class RenderWindow(
textures.allTextures.add(Texture(RenderConstants.DEBUG_TEXTURE_RESOURCE_LOCATION))
WHITE_TEXTURE = TextureLikeTexture(
texture = Texture(ResourceLocation("minosoft:textures/white.png")),
uvStart = Vec2(0, 0),
uvEnd = Vec2(1.0f, 1.0f),
size = Vec2i(16, 16)
)
textures.allTextures.add(WHITE_TEXTURE.texture)
font.load(connection.assetsManager)

View File

@ -21,12 +21,10 @@ import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Renderer
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
import de.bixilon.minosoft.gui.rendering.hud.elements.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.elements.chat.ChatBoxHUDElement
import de.bixilon.minosoft.gui.rendering.hud.elements.debug.HUDSystemDebugElement
import de.bixilon.minosoft.gui.rendering.hud.elements.debug.HUDWorldDebugElement
import de.bixilon.minosoft.gui.rendering.hud.elements.other.CrosshairHUDElement
import de.bixilon.minosoft.gui.rendering.hud.elements.other.HotbarHUDElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
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.shader.Shader
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
@ -73,30 +71,22 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
}
private fun registerDefaultElements() {
addElement(ElementsNames.HOTBAR_RESOURCE_LOCATION, HotbarHUDElement(this), HUDElementProperties(
position = Vec2(0.0f, -1.0f),
xBinding = HUDElementProperties.PositionBindings.CENTER,
))
addElement(ElementsNames.CROSSHAIR_RESOURCE_LOCATION, CrosshairHUDElement(this), HUDElementProperties(
position = Vec2(0.0f, 0.0f),
xBinding = HUDElementProperties.PositionBindings.CENTER,
yBinding = HUDElementProperties.PositionBindings.CENTER,
))
addElement(ElementsNames.WORLD_DEBUG_SCREEN_RESOURCE_LOCATION, HUDWorldDebugElement(this), HUDElementProperties(
addElement(ElementsNames.WORLD_DEBUG_SCREEN_RESOURCE_LOCATION, HUDWorldDebugNode(this), HUDElementProperties(
position = Vec2(-1.0f, 1.0f),
toggleKeyBinding = KeyBindingsNames.TOGGLE_DEBUG_SCREEN,
enabled = false,
))
addElement(ElementsNames.SYSTEM_DEBUG_SCREEN_RESOURCE_LOCATION, HUDSystemDebugElement(this), HUDElementProperties(
addElement(ElementsNames.SYSTEM_DEBUG_SCREEN_RESOURCE_LOCATION, HUDSystemDebugNode(this), HUDElementProperties(
position = Vec2(1.0f, 1.0f),
toggleKeyBinding = KeyBindingsNames.TOGGLE_DEBUG_SCREEN,
enabled = false,
))
addElement(ElementsNames.CHAT_RESOURCE_LOCATION, ChatBoxHUDElement(this), HUDElementProperties(
position = Vec2(0.0f, -1.0f),
xBinding = HUDElementProperties.PositionBindings.CENTER,
))
}
fun addElement(resourceLocation: ResourceLocation, hudElement: HUDElement, defaultProperties: HUDElementProperties) {
@ -183,7 +173,7 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
if (forcePrepare || needsUpdate) {
for ((elementProperties, hudElement) in enabledHUDElement.values) {
val realScaleFactor = elementProperties.scale * Minosoft.getConfig().config.game.hud.scale
val realSize = Vec2i(hudElement.layout.fakeX ?: (hudElement.layout.size.x * realScaleFactor), hudElement.layout.fakeY ?: (hudElement.layout.size.y * realScaleFactor))
val realSize = hudElement.layout.sizing.currentSize * realScaleFactor
val elementStart = getRealPosition(realSize, elementProperties, renderWindow.screenDimensions)

View File

@ -0,0 +1,38 @@
/*
* 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.
*/
/*
* 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.atlas
import de.bixilon.minosoft.gui.rendering.textures.Texture
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
class TextureLikeTexture(
override val texture: Texture,
override val uvStart: Vec2,
override val uvEnd: Vec2,
override val size: Vec2i,
) : TextureLike

View File

@ -1,64 +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.chat
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.elements.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.elements.input.SubmittableTextField
import glm_.vec2.Vec2i
class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer) {
private lateinit var inputField: SubmittableTextField
override fun init() {
inputField = SubmittableTextField(font = hudRenderer.renderWindow.font, z = 100, maxLength = 256, onSubmit = {
try {
hudRenderer.renderWindow.connection.sender.sendChatMessage(it)
closeChat()
return@SubmittableTextField true
} catch (exception: Exception) {
closeChat()
return@SubmittableTextField false
}
})
layout.addChild(inputField)
hudRenderer.renderWindow.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) { _, _ ->
openChat()
}
hudRenderer.renderWindow.registerKeyCallback(KeyBindingsNames.CLOSE_CHAT) { _, _ ->
closeChat()
}
}
override fun screenChangeResizeCallback(screenDimensions: Vec2i) {
layout.fakeX = screenDimensions.x - 2 // 1 pixel padding on every side
inputField.fakeX = layout.fakeX
}
fun openChat() {
hudRenderer.renderWindow.currentKeyConsumer = inputField
hudRenderer.renderWindow.currentElement.remove(KeyBindingsNames.WHEN_IN_GAME)
hudRenderer.renderWindow.currentElement.add(KeyBindingsNames.WHEN_IN_CHAT)
}
fun closeChat() {
inputField.clearText()
hudRenderer.renderWindow.currentKeyConsumer = null
hudRenderer.renderWindow.currentElement.remove(KeyBindingsNames.WHEN_IN_CHAT)
hudRenderer.renderWindow.currentElement.add(KeyBindingsNames.WHEN_IN_GAME)
}
}

View File

@ -21,6 +21,5 @@ interface KeyConsumer {
fun charInput(char: Char) {}
fun keyInput(keyCodes: KeyCodes) {
}
fun keyInput(keyCodes: KeyCodes) {}
}

View File

@ -1,46 +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.gui.rendering.font.Font
import glm_.vec2.Vec2i
class SubmittableTextField(
start: Vec2i = Vec2i(0, 0),
z: Int = 0,
font: Font,
defaultText: String = "",
maxLength: Int = 256,
private val onSubmit: (text: String) -> Boolean,
) : TextField(start, z, font, defaultText, maxLength) {
fun submit() {
if (!onSubmit.invoke(text)) {
// failed
return
}
text = ""
}
override fun keyInput(keyCodes: KeyCodes) {
if (keyCodes == KeyCodes.KEY_ENTER) {
// submit
submit()
return
}
super.keyInput(keyCodes)
}
}

View File

@ -1,104 +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.RenderConstants
import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.ImageElement
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.Layout
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.TextElement
import de.bixilon.minosoft.util.MMath
import glm_.vec2.Vec2i
open class TextField(
start: Vec2i = Vec2i(0, 0),
z: Int = 0,
font: Font,
defaultText: String = "",
var maxLength: Int = 256,
) : Layout(start, z), KeyConsumer, MouseConsumer {
override var focused: Boolean = true
private var textBuilder: StringBuilder = StringBuilder(defaultText)
private val textElement = TextElement(ChatComponent.valueOf(raw = text), font, background = false)
private var position = text.length
var text: String
get() = textBuilder.toString()
set(value) {
position = value.length
textBuilder = StringBuilder(value)
update()
}
init {
addChild(textElement)
addChild(ImageElement(Vec2i(0, 0), null, Vec2i(-1), z, RenderConstants.TEXT_BACKGROUND_COLOR))
}
fun clearText() {
textBuilder.clear()
update()
}
private fun update() {
textElement.text = ChatComponent.valueOf(raw = text)
}
override fun keyInput(keyCodes: KeyCodes) {
when (keyCodes) {
KeyCodes.KEY_BACKSPACE -> {
if (textBuilder.isEmpty()) {
return
}
textBuilder.deleteCharAt(--position)
}
KeyCodes.KEY_DELETE -> {
if (textBuilder.isEmpty() || position == textBuilder.length) {
return
}
textBuilder.deleteCharAt(position)
}
KeyCodes.KEY_ENTER -> {
if (position > maxLength) {
return
}
textBuilder.insert(position++, '\n')
}
KeyCodes.KEY_LEFT -> {
position = MMath.clamp(position - 1, 0, text.length)
return
}
KeyCodes.KEY_RIGHT -> {
position = MMath.clamp(position + 1, 0, text.length)
return
}
// ToDo: Up and down for line breaks, shift and ctrl modifier, ...
else -> {
return
}
}
update()
super.keyInput(keyCodes)
}
override fun charInput(char: Char) {
if (position >= maxLength) {
return
}
textBuilder.insert(position++, char.toString())
update()
}
}

View File

@ -15,17 +15,19 @@ package de.bixilon.minosoft.gui.rendering.hud.elements.other
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.elements.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.ImageElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.ImageNode
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
import glm_.vec2.Vec2i
class CrosshairHUDElement(
hudRender: HUDRenderer,
) : HUDElement(hudRender) {
private lateinit var crosshairImage: ImageElement
private lateinit var crosshairImage: ImageNode
override fun init() {
val atlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:crosshair")]!!
crosshairImage = ImageElement(end = atlasElement.binding.size, textureLike = atlasElement)
layout.addChild(crosshairImage)
crosshairImage = ImageNode(hudRenderer.renderWindow, NodeSizing(minSize = atlasElement.binding.size), textureLike = atlasElement)
layout.addChild(Vec2i(0, 0), crosshairImage)
}
}

View File

@ -1,187 +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.config.config.game.controls.KeyBindingsNames
import de.bixilon.minosoft.data.Gamemodes
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.text.TextComponent
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
import de.bixilon.minosoft.gui.rendering.hud.elements.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.*
import de.bixilon.minosoft.modding.event.EventInvokerCallback
import de.bixilon.minosoft.modding.event.events.ChangeGameStateEvent
import de.bixilon.minosoft.modding.event.events.ExperienceChangeEvent
import de.bixilon.minosoft.modding.event.events.HeldItemChangeEvent
import de.bixilon.minosoft.modding.event.events.UpdateHealthEvent
import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketChangeGameState
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
class HotbarHUDElement(
hudRender: HUDRenderer,
) : HUDElement(hudRender) {
private lateinit var hotbarBase: HotbarBaseElement
private lateinit var experienceBar: ProgressBar
private lateinit var levelText: TextElement
private lateinit var healthBar: HealthBar
override fun init() {
hotbarBase = HotbarBaseElement(
baseHUDAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:hotbar_base")]!!,
frameHUDAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:hotbar_selected_slot_frame")]!!
)
experienceBar = ProgressBar(
emptyAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:experience_bar_empty")]!!,
fullAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:experience_bar_full")]!!,
z = 1,
)
levelText = TextElement(
font = hudRenderer.renderWindow.font,
background = false,
z = 2,
)
healthBar = HealthBar(
blackHeartContainerAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:black_heart_container")]!!,
whiteHeartContainerAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:white_heart_container")]!!,
halfHartAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:half_red_heart")]!!,
hartAtlasElement = hudRenderer.hudAtlasElements[ResourceLocation("minecraft:full_red_heart")]!!,
maxValue = 20.0f,
textReplaceValue = 40.0f,
textColor = RenderConstants.HP_TEXT_COLOR,
font = hudRenderer.renderWindow.font,
z = 5,
)
registerEvents()
prepare()
}
private fun registerEvents() {
for ((slotIndex, resourceLocation) in KeyBindingsNames.SELECT_HOTBAR_SLOTS.withIndex()) {
hudRenderer.renderWindow.registerKeyCallback(resourceLocation) { _, _ ->
hudRenderer.connection.sender.selectSlot(slotIndex)
prepare()
}
}
hudRenderer.connection.registerEvent(EventInvokerCallback<ExperienceChangeEvent> {
experienceBar.progress = it.bar
levelText.text = TextComponent(it.level.toString()).color(RenderConstants.EXPERIENCE_BAR_LEVEL_COLOR)
experienceBar.prepare()
prepare()
})
hudRenderer.connection.registerEvent(EventInvokerCallback<HeldItemChangeEvent> {
hotbarBase.selectedSlot = it.slot
hotbarBase.prepare()
prepare()
})
hudRenderer.connection.registerEvent(EventInvokerCallback<ChangeGameStateEvent> {
if (it.reason != PacketChangeGameState.Reason.CHANGE_GAMEMODE) {
return@EventInvokerCallback
}
prepare()
})
hudRenderer.connection.registerEvent(EventInvokerCallback<UpdateHealthEvent> {
healthBar.value = it.health
healthBar.prepare()
prepare()
})
}
private fun prepare() {
layout.clear()
if (hudRenderer.connection.player.entity.gamemode == Gamemodes.SPECTATOR) {
// ToDo: Spectator hotbar
return
}
if (hudRenderer.connection.player.entity.gamemode != Gamemodes.CREATIVE) {
// add health bar, hunger, armor, experience and more
layout.addChild(healthBar)
// if (hudRenderer.connection.player.level != 0) {
// experience
levelText.start = Vec2i((hotbarBase.size.x - levelText.size.x) / 2, layout.size.y - (levelText.size.y - ELEMENT_PADDING) + ELEMENT_PADDING)
layout.addChild(levelText)
// }
// experience bar
experienceBar.start = Vec2i(0, levelText.start.y + levelText.size.y - ELEMENT_PADDING)
layout.addChild(experienceBar)
}
hotbarBase.start = Vec2i(0, layout.size.y + ELEMENT_PADDING)
layout.addChild(hotbarBase)
}
companion object {
private const val ELEMENT_PADDING = 2
}
class HotbarBaseElement(
start: Vec2i = Vec2i(0, 0),
val baseHUDAtlasElement: HUDAtlasElement,
val frameHUDAtlasElement: HUDAtlasElement,
z: Int = 1,
) : Layout(start, z) {
private var _selectedSlot = 0
var selectedSlot: Int
get() = _selectedSlot
set(value) {
_selectedSlot = value
prepare()
}
private val base = ImageElement(textureLike = baseHUDAtlasElement)
private val frame = ImageElement(textureLike = frameHUDAtlasElement, z = 2)
init {
fakeX = base.size.x
addChild(base)
addChild(frame)
}
fun prepare() {
// selectedFrame
val slotBinding = baseHUDAtlasElement.slots[selectedSlot] ?: return
val frameSlotBinding = frameHUDAtlasElement.slots[0] ?: return
val frameSizeFactor = slotBinding.size / frameSlotBinding.size
val selectedFrameOffset = Vec2(((frameHUDAtlasElement.binding.size.y * frameSizeFactor.y) - baseHUDAtlasElement.binding.size.y) * 2)
frame.start = slotBinding.start - selectedFrameOffset
frame.end = slotBinding.end + selectedFrameOffset
cache.clear()
}
}
}

View File

@ -1,135 +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.primitive
import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.data.text.TextComponent
import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
import de.bixilon.minosoft.util.MMath
import glm_.mat4x4.Mat4
import glm_.vec2.Vec2i
class HealthBar(
start: Vec2i = Vec2i(0, 0),
var blackHeartContainerAtlasElement: HUDAtlasElement,
var whiteHeartContainerAtlasElement: HUDAtlasElement,
var halfHartAtlasElement: HUDAtlasElement,
var hartAtlasElement: HUDAtlasElement,
var maxValue: Float,
var textReplaceValue: Float,
var textColor: RGBColor,
var font: Font,
z: Int = 1,
) : Layout(start, z) {
private val singleHeartSize = blackHeartContainerAtlasElement.binding.size
private val width = singleHeartSize.x * MAX_HEARTS_IN_ROW
private val alternativeText = TextElement(font = font, start = Vec2i(0, 0), background = false)
private var _value = 0.0f
var value: Float
get() = _value
set(value) {
_value = if (value < 0.0f) {
0.0f
} else {
value
}
cache.clear()
}
fun prepare() {
clear()
if (value >= textReplaceValue) {
alternativeText.text = TextComponent(value.toString()).color(textColor)
alternativeText.start = Vec2i((width - alternativeText.size.x) / 2, 0)
addChild(alternativeText)
return
}
val offset = Vec2i(0, 0)
val containerCount = (maxValue + 1.0f).toInt() / 2
// heart container
val rows = MMath.divideUp(containerCount, MAX_HEARTS_IN_ROW)
for (row in 0 until rows) {
val heartsToDraw = if (row == 0 && containerCount % MAX_HEARTS_IN_ROW != 0) {
containerCount % MAX_HEARTS_IN_ROW
} else {
MAX_HEARTS_IN_ROW
}
for (i in 0 until heartsToDraw) {
drawHeart(this.start + offset, blackHeartContainerAtlasElement, z)
offset.x += singleHeartSize.x - 1
}
offset.y += singleHeartSize.y
offset.x = 0
}
offset.x = 0
offset.y = 0
val halfHeartCount = MMath.round10Up(value)
val fullHeartCount = halfHeartCount / 2
val addHalfHeart = halfHeartCount % 2 == 1
var currentHeart = fullHeartCount - 1
if (addHalfHeart) {
currentHeart += 1
}
for (row in rows - 1 downTo 0) {
val heartsInRow = if (row == 0 && containerCount % MAX_HEARTS_IN_ROW != 0) {
containerCount % MAX_HEARTS_IN_ROW
} else {
MAX_HEARTS_IN_ROW
}
for (i in 0 until heartsInRow) {
if (currentHeart < 0) {
break
}
if (currentHeart == 0 && addHalfHeart) {
drawHeart(this.start + offset, halfHartAtlasElement, z + 1)
} else {
drawHeart(this.start + offset, hartAtlasElement, z + 1)
}
currentHeart--
offset.x += singleHeartSize.x - 1
}
offset.y += singleHeartSize.y
offset.x = 0
}
}
override fun prepareCache(start: Vec2i, scaleFactor: Float, matrix: Mat4, z: Int) {
prepare()
super.prepareCache(start, scaleFactor, matrix, z)
}
private fun drawHeart(elementStart: Vec2i, element: HUDAtlasElement, z: Int) {
addChild(ImageElement(elementStart, element, elementStart + singleHeartSize, this.z + z))
}
companion object {
const val MAX_HEARTS_IN_ROW = 10
}
}

View File

@ -1,125 +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.primitive
import glm_.mat4x4.Mat4
import glm_.vec2.Vec2i
open class Layout(
start: Vec2i,
val z: Int,
) : Element(start) {
override var size: Vec2i
get() = Vec2i(fakeX ?: super.size.x, fakeY ?: super.size.y)
set(value) {
super.size = value
}
private val children: MutableList<Element> = mutableListOf()
var fakeX: Int? = null
var fakeY: Int? = null
fun clear() {
synchronized(children) {
children.clear()
}
clearCache()
recalculateSize()
}
fun finishBatchAdd() {
cache.clear()
recalculateSize()
}
fun batchAdd(child: Element) {
child.parent = this
synchronized(children) {
children.add(child)
}
}
fun addChild(child: Element) {
batchAdd(child)
finishBatchAdd()
}
override fun recalculateSize() {
if (children.isEmpty()) {
size = Vec2i(0, 0)
} else {
synchronized(children) {
for (child in children) {
checkSize(child.start + child.size)
}
}
}
parent?.recalculateSize()
}
override fun clearCache() {
cache.clear()
parent?.clearCache()
}
private fun checkSize(vec2: Vec2i) {
var changed = false
if (vec2.x > size.x) {
size.x = vec2.x
changed = true
}
if (vec2.y > size.y) {
size.y = vec2.y
changed = true
}
if (changed) {
clearCache()
}
}
fun pushChildrenToRight(offset: Int = 0) {
for (child in children) {
child.start = Vec2i((size.x - child.size.x) - offset, child.start.y)
child.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) {
val normalStart = addToStart(start, this.start * scaleFactor)
synchronized(children) {
for (child in children) {
child.checkCache(normalStart, scaleFactor, matrix, this.z + z)
cache.addCache(child.cache)
}
}
}
fun clearChildrenCache() {
synchronized(children) {
for (child in children) {
if (child is Layout) {
child.clearChildrenCache()
}
child.clearCache()
}
}
clearCache()
}
}

View File

@ -1,66 +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.primitive
import de.bixilon.minosoft.gui.rendering.hud.atlas.HUDAtlasElement
import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLike
import de.bixilon.minosoft.gui.rendering.textures.Texture
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
class ProgressBar(
start: Vec2i = Vec2i(0, 0),
val emptyAtlasElement: HUDAtlasElement,
end: Vec2i = emptyAtlasElement.size,
val fullAtlasElement: HUDAtlasElement,
z: Int = 1,
) : Layout(start, z) {
private var _progress = 0.0f
var progress: Float
get() = _progress
set(value) {
check(value >= 0.0f) { "Value is smaller than 0" }
check(value <= 1.0f) { "Value is greater than 1" }
prepare()
_progress = value
}
private val emptyImage = ImageElement(this.start, emptyAtlasElement, end, z)
private val fullImage = ImageElement(this.start, fullAtlasElement, end, z)
init {
addChild(emptyImage)
addChild(fullImage)
recalculateSize()
}
override fun recalculateSize() {
size = emptyAtlasElement.binding.size
}
fun prepare() {
fullImage.textureLike = object : TextureLike {
override val texture: Texture
get() = fullAtlasElement.texture
override val uvStart: Vec2
get() = fullAtlasElement.uvStart
override val uvEnd: Vec2
get() = Vec2((fullAtlasElement.uvEnd.x - fullAtlasElement.uvStart.x) * progress + fullAtlasElement.uvStart.x, fullAtlasElement.uvEnd.y)
override val size: Vec2i
get() = this@ProgressBar.size
}
cache.clear()
}
}

View File

@ -11,14 +11,14 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.hud.elements
package de.bixilon.minosoft.gui.rendering.hud.nodes
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.Layout
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
import glm_.vec2.Vec2i
abstract class HUDElement(protected val hudRenderer: HUDRenderer) {
val layout = Layout(Vec2i(), 0)
val layout = AbsoluteLayout(hudRenderer.renderWindow)
open fun init() {}
open fun postInit() {}

View File

@ -11,21 +11,22 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.hud.elements.debug
package de.bixilon.minosoft.gui.rendering.hud.nodes.debug
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.elements.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.TextElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.primitive.LabelNode
import glm_.vec2.Vec2i
abstract class DebugScreen(hudRenderer: HUDRenderer) : HUDElement(hudRenderer) {
abstract class DebugScreenNode(hudRenderer: HUDRenderer) : HUDElement(hudRenderer) {
protected var lastPrepareTime = 0L
fun text(text: String = ""): TextElement {
val textElement = TextElement(ChatComponent.valueOf(raw = text), hudRenderer.renderWindow.font, Vec2i(2, layout.size.y + RenderConstants.TEXT_LINE_PADDING))
layout.addChild(textElement)
fun text(text: String = ""): LabelNode {
val textElement = LabelNode(hudRenderer.renderWindow, text = ChatComponent.valueOf(raw = text))
layout.addChild(Vec2i(0, layout.sizing.currentSize.y + RenderConstants.TEXT_LINE_PADDING), textElement)
layout.apply()
return textElement
}
}

View File

@ -11,9 +11,10 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.hud.elements.debug
package de.bixilon.minosoft.gui.rendering.hud.nodes.debug
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeAlignment
import de.bixilon.minosoft.modding.loading.ModLoader
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.GitInfo
@ -23,9 +24,12 @@ import glm_.vec2.Vec2i
import org.lwjgl.opengl.GL11.*
class HUDSystemDebugElement(hudRenderer: HUDRenderer) : DebugScreen(hudRenderer) {
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")
}
@ -59,7 +63,6 @@ class HUDSystemDebugElement(hudRenderer: HUDRenderer) : DebugScreen(hudRenderer)
override fun screenChangeResizeCallback(screenDimensions: Vec2i) {
displayText.sText = "Display: ${getScreenDimensions()}"
layout.pushChildrenToRight(1)
}
override fun init() {
@ -73,7 +76,7 @@ class HUDSystemDebugElement(hudRenderer: HUDRenderer) : DebugScreen(hudRenderer)
}
memoryText.sText = "Memory: ${getUsedMemoryPercent()}% ${getFormattedUsedMemory()}/${SystemInformation.MAX_MEMORY_TEXT}"
allocatedMemoryText.sText = "Allocated: ${getAllocatedMemoryPercent()}% ${getFormattedAllocatedMemory()}"
layout.pushChildrenToRight(1)
lastPrepareTime = System.currentTimeMillis()
}

View File

@ -11,18 +11,25 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.hud.elements.debug
package de.bixilon.minosoft.gui.rendering.hud.nodes.debug
import de.bixilon.minosoft.data.Directions
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
class HUDWorldDebugElement(hudRenderer: HUDRenderer) : DebugScreen(hudRenderer) {
class HUDWorldDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer) {
private val camera = hudRenderer.renderWindow.camera
private val brandText = text("§cMinosoft 0.1-pre1")
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")

View File

@ -0,0 +1,137 @@
/*
* 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.MMath
import glm_.mat4x4.Mat4
import glm_.vec2.Vec2i
import java.util.concurrent.ConcurrentHashMap
open class AbsoluteLayout(
renderWindow: RenderWindow,
sizing: NodeSizing = NodeSizing(),
initialCacheSize: Int = DEFAULT_INITIAL_CACHE_SIZE,
) : Node(renderWindow, sizing, initialCacheSize) {
protected val children: MutableMap<Node, Vec2i> = ConcurrentHashMap()
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()
}
fun recursiveApply() {
for ((child, _) in children) {
if (child is AbsoluteLayout) {
child.recursiveApply()
} else {
child.apply()
}
}
}
private fun checkAlignment() {
when (sizing.forceAlign) {
NodeAlignment.RIGHT -> {
for ((child, start) in children) {
start.x = sizing.currentSize.x - (child.sizing.margin.right + sizing.padding.right + child.sizing.currentSize.x)
}
}
NodeAlignment.LEFT -> {
for ((child, start) in children) {
start.x = child.sizing.margin.left + sizing.padding.left
}
}
NodeAlignment.CENTER -> {
for ((child, start) in children) {
start.x = (sizing.currentSize.x - child.sizing.currentSize.x) / 2
}
}
}
}
override fun apply() {
clearCache()
recalculateSize()
checkAlignment()
parent?.apply()
}
private fun recalculateSize() {
if (children.isEmpty()) {
sizing.currentSize.x = sizing.minSize.x
sizing.currentSize.y = sizing.minSize.y
} else {
for ((childNode, start) in children) {
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) {
child.checkCache(addToStart(start, childStart * scaleFactor), scaleFactor, matrix, z)
cache.addCache(child.cache)
}
}
fun clearChildrenCache() {
for ((child, _) in children) {
if (child is AbsoluteLayout) {
child.clearChildrenCache()
} else {
child.clearCache()
}
}
clearCache()
}
}

View File

@ -11,34 +11,27 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.hud.elements.primitive
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.HUDMesh
import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLike
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
import glm_.mat4x4.Mat4
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
import glm_.vec3.Vec3
import glm_.vec4.Vec4
class ImageElement(
start: Vec2i = Vec2i(0, 0),
class ImageNode(
renderWindow: RenderWindow,
sizing: NodeSizing = NodeSizing(),
var textureLike: TextureLike?,
end: Vec2i = textureLike?.size ?: Vec2i(0, 0),
val z: Int = 0,
val tintColor: RGBColor? = null,
) : EndElement(start, end, initialCacheSize = HUDMesh.FLOATS_PER_VERTEX * 6) {
init {
recalculateSize()
}
override fun recalculateSize() {
size = end - start
parent?.recalculateSize()
}
) : Node(renderWindow, sizing = sizing, initialCacheSize = HUDMesh.FLOATS_PER_VERTEX * 6) {
private fun addToStart(start: Vec2i, elementPosition: Vec2i): Vec2i {
@ -49,22 +42,11 @@ class ImageElement(
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 ourStart = addToStart(start, this.start * scaleFactor)
val modelStart = matrix * Vec4(RenderConstants.PIXEL_UV_PIXEL_ADD + ourStart, 1.0f, 1.0f)
val realEnd = Vec2i(
x = if (end.x == -1) {
parent!!.size.x
} else {
end.x * scaleFactor
},
y = if (end.y == -1) {
parent!!.size.y
} else {
end.y * scaleFactor
}
)
val ourEnd = addToEnd(start, realEnd)
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()

View File

@ -11,28 +11,31 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.hud.elements.primitive
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.hud.nodes.layout.AbsoluteLayout
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeSizing
import glm_.vec2.Vec2i
class TextElement(
private var _text: ChatComponent = ChatComponent.valueOf(raw = ""),
private val font: Font,
start: Vec2i = Vec2i(0, 0),
z: Int = 1,
class LabelNode(
renderWindow: RenderWindow,
sizing: NodeSizing = NodeSizing(minSize = Vec2i(0, Font.CHAR_HEIGHT)),
text: ChatComponent = ChatComponent.valueOf(raw = ""),
var background: Boolean = true,
) : Layout(start, z) {
) : AbsoluteLayout(renderWindow, sizing) {
private var _text: ChatComponent = text
var text: ChatComponent
get() = _text
set(value) {
size = Vec2i(0, 0)
_text = value
prepare()
apply()
}
var sText: String
get() = text.message
@ -45,22 +48,17 @@ class TextElement(
}
private fun prepare() {
clear()
if (text.message.isBlank()) {
fakeY = Font.CHAR_HEIGHT
} else {
fakeY = null
clearChildren()
val textSize = Vec2i(0, 0)
text.prepareRender(Vec2i(1, 1), Vec2i(), font, this, this.z + z + 1, textSize)
finishBatchAdd()
text.prepareRender(Vec2i(1, 1), Vec2i(), renderWindow, this, 1, textSize)
apply()
if (background) {
drawBackground(textSize + 1, z)
}
drawBackground(textSize + 1)
}
}
private fun drawBackground(end: Vec2i, z: Int, tintColor: RGBColor = RenderConstants.TEXT_BACKGROUND_COLOR) {
addChild(ImageElement(Vec2i(0, 0), null, end, this.z + z, tintColor))
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))
}
}

View File

@ -11,31 +11,23 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.hud.elements.primitive
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 Element(
private var _start: Vec2i,
initialCacheSize: Int = 1000,
abstract class Node(
val renderWindow: RenderWindow,
val sizing: NodeSizing = NodeSizing(),
initialCacheSize: Int = DEFAULT_INITIAL_CACHE_SIZE,
) {
var start: Vec2i
get() {
return _start
}
set(value) {
_start = value
parent?.recalculateSize()
clearCache()
}
val cache = HUDCacheMesh(initialCacheSize)
open var parent: Element? = null
open var size: Vec2i = Vec2i()
open var parent: Node? = null
abstract fun recalculateSize()
abstract fun apply()
fun needsCacheUpdate(): Boolean {
return cache.isEmpty()
@ -53,4 +45,8 @@ abstract class Element(
}
abstract fun prepareCache(start: Vec2i, scaleFactor: Float, matrix: Mat4, z: Int = 1)
companion object {
const val DEFAULT_INITIAL_CACHE_SIZE = 1000
}
}

View File

@ -0,0 +1,21 @@
/*
* 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,
}

View File

@ -11,23 +11,16 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.hud.elements.primitive
package de.bixilon.minosoft.gui.rendering.hud.nodes.properties
import glm_.vec2.Vec2i
abstract class EndElement(
start: Vec2i,
private var _end: Vec2i,
initialCacheSize: Int = 10000,
) : Element(start, initialCacheSize = initialCacheSize) {
var end: Vec2i
get() {
return _end
}
set(value) {
_end = value
parent?.recalculateSize()
clearCache()
}
data class NodeSizing(
val minSize: Vec2i = Vec2i(0, 0),
val margin: Spacing = Spacing(),
val padding: Spacing = Spacing(),
val maxSize: Vec2i = Vec2i(Int.MAX_VALUE, Int.MAX_VALUE),
var forceAlign: NodeAlignment? = null,
) {
val currentSize: Vec2i = Vec2i(minSize)
}

View File

@ -0,0 +1,21 @@
/*
* 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,
)

View File

@ -47,12 +47,7 @@ void main() {
texelColor *= passTintColor;
}
// ToDo
if (passTintColor.r == 0.0f && passTintColor.g == 0.0f && passTintColor.b == 0.0f && passTintColor.a != 0.0f){
outColor= vec4(passTintColor.rgb * (vec3(1.0f) / texelColor.rgb), passTintColor.a);
} else {
outColor = texelColor;
}
//
// outColor = vec4(1.0f, 0.0f, 0.5f, 1.0f);

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B