mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-16 10:55:01 -04:00
TextComponent: Default formatting, hud rendering improvements
This commit is contained in:
parent
dcb8a05cb5
commit
cc166127f8
@ -42,7 +42,7 @@ class BaseComponent : ChatComponent {
|
|||||||
constructor(parent: TextComponent? = null, legacy: String = "", restrictedMode: Boolean = false) {
|
constructor(parent: TextComponent? = null, legacy: String = "", restrictedMode: Boolean = false) {
|
||||||
val currentText = StringBuilder()
|
val currentText = StringBuilder()
|
||||||
var currentColor = parent?.color
|
var currentColor = parent?.color
|
||||||
val currentFormatting: MutableSet<ChatFormattingCode> = parent?.formatting?.toMutableSet() ?: mutableSetOf()
|
var currentFormatting: MutableSet<ChatFormattingCode> = parent?.formatting?.toMutableSet() ?: TextComponent.DEFAULT_FORMATTING.toMutableSet()
|
||||||
|
|
||||||
val iterator = StringCharacterIterator(legacy)
|
val iterator = StringCharacterIterator(legacy)
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ class BaseComponent : ChatComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
push(null)
|
push(null)
|
||||||
currentFormatting.clear()
|
currentFormatting = TextComponent.DEFAULT_FORMATTING.toMutableSet()
|
||||||
currentColor = null
|
currentColor = null
|
||||||
currentText.clear()
|
currentText.clear()
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ class BaseComponent : ChatComponent {
|
|||||||
|
|
||||||
val color = json["color"]?.nullCast<String>()?.toColor() ?: parent?.color
|
val color = json["color"]?.nullCast<String>()?.toColor() ?: parent?.color
|
||||||
|
|
||||||
val formatting = parent?.formatting?.toMutableSet() ?: mutableSetOf()
|
val formatting = parent?.formatting?.toMutableSet() ?: TextComponent.DEFAULT_FORMATTING.toMutableSet()
|
||||||
|
|
||||||
formatting.addOrRemove(PreChatFormattingCodes.BOLD, json["bold"]?.toBoolean())
|
formatting.addOrRemove(PreChatFormattingCodes.BOLD, json["bold"]?.toBoolean())
|
||||||
formatting.addOrRemove(PreChatFormattingCodes.ITALIC, json["italic"]?.toBoolean())
|
formatting.addOrRemove(PreChatFormattingCodes.ITALIC, json["italic"]?.toBoolean())
|
||||||
|
@ -32,7 +32,7 @@ import javafx.util.Duration
|
|||||||
open class TextComponent(
|
open class TextComponent(
|
||||||
message: Any? = "",
|
message: Any? = "",
|
||||||
override var color: RGBColor? = null,
|
override var color: RGBColor? = null,
|
||||||
override val formatting: MutableSet<ChatFormattingCode> = mutableSetOf(),
|
override val formatting: MutableSet<ChatFormattingCode> = DEFAULT_FORMATTING.toMutableSet(),
|
||||||
var clickEvent: ClickEvent? = null,
|
var clickEvent: ClickEvent? = null,
|
||||||
var hoverEvent: HoverEvent? = null,
|
var hoverEvent: HoverEvent? = null,
|
||||||
) : ChatComponent, TextStyle {
|
) : ChatComponent, TextStyle {
|
||||||
@ -191,4 +191,8 @@ open class TextComponent(
|
|||||||
}
|
}
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val DEFAULT_FORMATTING: Set<ChatFormattingCode> = setOf(PreChatFormattingCodes.SHADOWED)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,12 @@ import glm_.vec2.Vec2i
|
|||||||
|
|
||||||
object BaseComponentRenderer : ChatComponentRenderer<BaseComponent> {
|
object BaseComponentRenderer : ChatComponentRenderer<BaseComponent> {
|
||||||
|
|
||||||
override fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, z: Int, element: Element, fontAlignment: ElementAlignments, renderWindow: RenderWindow, consumer: GUIVertexConsumer?, renderInfo: TextRenderInfo, text: BaseComponent) {
|
override fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, z: Int, element: Element, fontAlignment: ElementAlignments, renderWindow: RenderWindow, consumer: GUIVertexConsumer?, renderInfo: TextRenderInfo, text: BaseComponent): Boolean {
|
||||||
for (part in text.parts) {
|
for (part in text.parts) {
|
||||||
ChatComponentRenderer.render(initialOffset, offset, size, z, element, fontAlignment, renderWindow, consumer, renderInfo, part)
|
if (ChatComponentRenderer.render(initialOffset, offset, size, z, element, fontAlignment, renderWindow, consumer, renderInfo, part)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,16 @@ import glm_.vec2.Vec2i
|
|||||||
|
|
||||||
interface ChatComponentRenderer<T : ChatComponent> {
|
interface ChatComponentRenderer<T : ChatComponent> {
|
||||||
|
|
||||||
fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, z: Int, element: Element, fontAlignment: ElementAlignments, renderWindow: RenderWindow, consumer: GUIVertexConsumer?, renderInfo: TextRenderInfo, text: T)
|
/**
|
||||||
|
* Returns true if the text exceeded the maximum size
|
||||||
|
*/
|
||||||
|
fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, z: Int, element: Element, fontAlignment: ElementAlignments, renderWindow: RenderWindow, consumer: GUIVertexConsumer?, renderInfo: TextRenderInfo, text: T): Boolean
|
||||||
|
|
||||||
|
|
||||||
companion object : ChatComponentRenderer<ChatComponent> {
|
companion object : ChatComponentRenderer<ChatComponent> {
|
||||||
|
|
||||||
override fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, z: Int, element: Element, fontAlignment: ElementAlignments, renderWindow: RenderWindow, consumer: GUIVertexConsumer?, renderInfo: TextRenderInfo, text: ChatComponent) {
|
override fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, z: Int, element: Element, fontAlignment: ElementAlignments, renderWindow: RenderWindow, consumer: GUIVertexConsumer?, renderInfo: TextRenderInfo, text: ChatComponent): Boolean {
|
||||||
when (text) {
|
return when (text) {
|
||||||
is BaseComponent -> BaseComponentRenderer.render(initialOffset, offset, size, z, element, fontAlignment, renderWindow, consumer, renderInfo, text)
|
is BaseComponent -> BaseComponentRenderer.render(initialOffset, offset, size, z, element, fontAlignment, renderWindow, consumer, renderInfo, text)
|
||||||
is TextComponent -> TextComponentRenderer.render(initialOffset, offset, size, z, element, fontAlignment, renderWindow, consumer, renderInfo, text)
|
is TextComponent -> TextComponentRenderer.render(initialOffset, offset, size, z, element, fontAlignment, renderWindow, consumer, renderInfo, text)
|
||||||
else -> TODO("Don't know how to render ${text::class.java}")
|
else -> TODO("Don't know how to render ${text::class.java}")
|
||||||
|
@ -23,131 +23,142 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.ElementAlignments
|
|||||||
import de.bixilon.minosoft.gui.rendering.gui.elements.ElementAlignments.Companion.getOffset
|
import de.bixilon.minosoft.gui.rendering.gui.elements.ElementAlignments.Companion.getOffset
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||||
import de.bixilon.minosoft.util.MMath.ceil
|
import de.bixilon.minosoft.util.MMath.ceil
|
||||||
|
import de.bixilon.minosoft.util.logging.Log
|
||||||
|
import de.bixilon.minosoft.util.logging.LogLevels
|
||||||
|
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
|
||||||
|
|
||||||
override fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, z: Int, element: Element, fontAlignment: ElementAlignments, renderWindow: RenderWindow, consumer: GUIVertexConsumer?, renderInfo: TextRenderInfo, text: TextComponent) {
|
override fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, z: Int, element: Element, fontAlignment: ElementAlignments, renderWindow: RenderWindow, consumer: GUIVertexConsumer?, renderInfo: TextRenderInfo, text: TextComponent): Boolean {
|
||||||
val elementMaxSize = element.maxSize
|
val elementMaxSize = element.maxSize
|
||||||
// ToDo: Only 1 quad for the underline and the strikethrough
|
// ToDo: Only 1 quad for the underline and the strikethrough
|
||||||
var first = true
|
|
||||||
|
|
||||||
var currentLineInfo = renderInfo.lines.getOrElse(renderInfo.currentLine) {
|
var alignmentXOffset = 0
|
||||||
val lineInfo = TextLineInfo()
|
if (size.x >= elementMaxSize.x || size.y >= elementMaxSize.y) {
|
||||||
|
// The size is already bigger/equals the maximum size
|
||||||
renderInfo.lines += lineInfo
|
return true
|
||||||
lineInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun pushLine() {
|
fun addY(height: Int): Boolean {
|
||||||
renderInfo.currentLine++
|
val nextY = offset.y + height
|
||||||
currentLineInfo = TextLineInfo()
|
val nextSizeY = nextY - initialOffset.y + Font.CHAR_HEIGHT // add initial height for chars
|
||||||
renderInfo.lines += currentLineInfo
|
if (nextSizeY >= elementMaxSize.y) {
|
||||||
}
|
|
||||||
|
|
||||||
fun updateOffset() {
|
|
||||||
val renderInfo = renderInfo
|
|
||||||
offset.x = initialOffset.x
|
|
||||||
if (consumer != null) {
|
|
||||||
// set offset of the next line to match the expected alignment
|
|
||||||
offset.x += fontAlignment.getOffset(element.size.x, renderInfo.lines[renderInfo.currentLine].width)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return If the text can't fit into the layout anymore
|
|
||||||
*/
|
|
||||||
fun wrap(): Boolean {
|
|
||||||
val yAdd = Font.CHAR_HEIGHT + Font.VERTICAL_SPACING
|
|
||||||
if (size.y + yAdd > elementMaxSize.y) {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (consumer == null) {
|
offset.y = nextY
|
||||||
pushLine()
|
if (nextSizeY > size.y) {
|
||||||
} else {
|
size.y = nextSizeY
|
||||||
renderInfo.currentLine++
|
|
||||||
}
|
}
|
||||||
updateOffset()
|
|
||||||
|
|
||||||
offset.y += yAdd
|
|
||||||
size.y += yAdd
|
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
fun wrap(): Boolean {
|
||||||
* @return If the text can't fit into the layout anymore
|
if (addY(Font.CHAR_HEIGHT + Font.VERTICAL_SPACING)) {
|
||||||
*/
|
return true
|
||||||
fun add(x: Int): Boolean {
|
}
|
||||||
if (offset.x - initialOffset.x + x > elementMaxSize.x) {
|
renderInfo.currentLine++
|
||||||
|
offset.x = initialOffset.x
|
||||||
|
if (consumer == null) {
|
||||||
|
// preparing phase
|
||||||
|
renderInfo.lines += TextLineInfo()
|
||||||
|
} else {
|
||||||
|
if (renderInfo.currentLine >= renderInfo.lines.size) {
|
||||||
|
Log.log(LogMessageType.OTHER, LogLevels.FATAL) { "Crash because of $text (size=$size, maxSize=$elementMaxSize)" }
|
||||||
|
}
|
||||||
|
alignmentXOffset = fontAlignment.getOffset(element.size.x, renderInfo.lines[renderInfo.currentLine].width)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addX(width: Int, wrap: Boolean = true): Boolean {
|
||||||
|
val nextX = offset.x + width
|
||||||
|
val nextSizeX = nextX + alignmentXOffset - initialOffset.x
|
||||||
|
if (nextSizeX > elementMaxSize.x) {
|
||||||
|
if (!wrap) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
if (wrap()) {
|
if (wrap()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
} else {
|
return addX(width, false)
|
||||||
offset.x += x
|
|
||||||
if (consumer == null) {
|
|
||||||
currentLineInfo.width += x
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (consumer == null) {
|
||||||
if (size.x < offset.x - initialOffset.x) {
|
renderInfo.lines[renderInfo.currentLine].width += width
|
||||||
size.x += x
|
}
|
||||||
|
offset.x = nextX
|
||||||
|
if (nextSizeX > size.x) {
|
||||||
|
size.x = nextSizeX
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (offset.x == initialOffset.x) {
|
if (size.y == 0) {
|
||||||
updateOffset()
|
// Add initial height of the letter for the first line
|
||||||
|
val nextSizeY = Font.CHAR_HEIGHT
|
||||||
|
if (nextSizeY > elementMaxSize.y) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (consumer != null) {
|
||||||
|
alignmentXOffset = fontAlignment.getOffset(element.size.x, renderInfo.lines[renderInfo.currentLine].width)
|
||||||
|
} else {
|
||||||
|
renderInfo.lines += TextLineInfo() // add line 0
|
||||||
|
}
|
||||||
|
size.y = nextSizeY
|
||||||
}
|
}
|
||||||
|
|
||||||
for (char in text.message.toCharArray()) {
|
|
||||||
|
for (charCode in text.message.codePoints().toArray()) {
|
||||||
|
val char = charCode.toChar()
|
||||||
if (char == '\n') {
|
if (char == '\n') {
|
||||||
if (wrap()) {
|
if (wrap()) {
|
||||||
return
|
return true
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip wrapped spaces
|
// skip spaces that are wrapped (because of a line break)
|
||||||
if (offset.y != initialOffset.y && offset.x == initialOffset.x && char == ' ') {
|
if (offset.y != initialOffset.y && offset.x == initialOffset.x && char == ' ') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val charData = renderWindow.font[char] ?: continue
|
val charData = renderWindow.font[char] ?: continue
|
||||||
|
|
||||||
if (first) {
|
val charWidth = charData.calculateWidth(text)
|
||||||
first = false
|
var width = charWidth
|
||||||
|
|
||||||
// Add initial size
|
if (offset.x != initialOffset.x) {
|
||||||
if (size.y == 0) {
|
// add spacing between letters
|
||||||
size.y = Font.CHAR_HEIGHT + Font.VERTICAL_SPACING
|
width += Font.HORIZONTAL_SPACING
|
||||||
}
|
}
|
||||||
} else if (offset.x != initialOffset.x && add(Font.HORIZONTAL_SPACING)) { // ToDo: Only add space when char fits
|
val previousY = offset.y
|
||||||
return
|
|
||||||
|
if (addX(width)) {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
val width = charData.calculateWidth(text)
|
val letterOffset = Vec2i(offset.x + alignmentXOffset, offset.y)
|
||||||
|
|
||||||
if (offset.x == initialOffset.x && offset.x - initialOffset.x + width > element.maxSize.x) {
|
// remove width from the offset again
|
||||||
return
|
letterOffset.x -= charWidth
|
||||||
|
|
||||||
|
if (previousY != offset.y) {
|
||||||
|
// line was wrapped, we want to begin at the offset without the spacing
|
||||||
|
// ToDo: Remove Font.HORIZONTAL_SPACING
|
||||||
}
|
}
|
||||||
consumer?.let { charData.render(offset, z, text, it) }
|
|
||||||
|
|
||||||
if (consumer != null) {
|
consumer?.let { charData.render(letterOffset, z, text, it) }
|
||||||
|
|
||||||
|
if (consumer == null) {
|
||||||
renderInfo.lines[renderInfo.currentLine].chars += char
|
renderInfo.lines[renderInfo.currentLine].chars += char
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add(width)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text.formatting.contains(PreChatFormattingCodes.ITALIC)) {
|
if (text.formatting.contains(PreChatFormattingCodes.ITALIC)) {
|
||||||
val italicOffset = CharData.ITALIC_OFFSET.ceil
|
val italicOffset = CharData.ITALIC_OFFSET.ceil
|
||||||
offset.x += italicOffset
|
addX(italicOffset) // ToDo: Should this be forced?
|
||||||
size.x += italicOffset
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,10 @@ import glm_.vec4.Vec4i
|
|||||||
abstract class Element(val hudRenderer: HUDRenderer) {
|
abstract class Element(val hudRenderer: HUDRenderer) {
|
||||||
val renderWindow = hudRenderer.renderWindow
|
val renderWindow = hudRenderer.renderWindow
|
||||||
open var parent: Element? = null
|
open var parent: Element? = null
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
onParentChange()
|
||||||
|
}
|
||||||
open var prepared: Boolean = false
|
open var prepared: Boolean = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,6 +35,7 @@ import java.lang.Integer.max
|
|||||||
class RowLayout(
|
class RowLayout(
|
||||||
hudRenderer: HUDRenderer,
|
hudRenderer: HUDRenderer,
|
||||||
override var childAlignment: ElementAlignments = ElementAlignments.LEFT,
|
override var childAlignment: ElementAlignments = ElementAlignments.LEFT,
|
||||||
|
spacing: Int = 0,
|
||||||
) : Layout(hudRenderer), ChildAlignable {
|
) : Layout(hudRenderer), ChildAlignable {
|
||||||
private var _prefSize = Vec2i.EMPTY
|
private var _prefSize = Vec2i.EMPTY
|
||||||
|
|
||||||
@ -45,6 +46,12 @@ class RowLayout(
|
|||||||
get() = _prefSize
|
get() = _prefSize
|
||||||
set(value) {}
|
set(value) {}
|
||||||
|
|
||||||
|
var spacing: Int = spacing
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
children.clear()
|
children.clear()
|
||||||
}
|
}
|
||||||
@ -55,13 +62,14 @@ class RowLayout(
|
|||||||
var childYOffset = margin.top
|
var childYOffset = margin.top
|
||||||
var maxZ = 0
|
var maxZ = 0
|
||||||
for (child in children) {
|
for (child in children) {
|
||||||
val childZ = child.render(Vec2i(offset.x + margin.left + childAlignment.getOffset(size.x, child.size.x), offset.y + childYOffset), z, consumer)
|
val childZ = child.render(Vec2i(offset.x + margin.left + childAlignment.getOffset(size.x - margin.horizontal, child.size.x), offset.y + childYOffset), z, consumer)
|
||||||
if (maxZ < childZ) {
|
if (maxZ < childZ) {
|
||||||
maxZ = childZ
|
maxZ = childZ
|
||||||
}
|
}
|
||||||
childYOffset += child.margin.top
|
childYOffset += child.margin.top
|
||||||
childYOffset += child.size.y
|
childYOffset += child.size.y
|
||||||
childYOffset += child.margin.bottom
|
childYOffset += child.margin.bottom
|
||||||
|
childYOffset += spacing
|
||||||
}
|
}
|
||||||
|
|
||||||
return maxZ
|
return maxZ
|
||||||
@ -125,6 +133,9 @@ class RowLayout(
|
|||||||
if (addY(child.margin.bottom)) {
|
if (addY(child.margin.bottom)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if (addY(spacing)) { // ToDo: Only add of not the last element
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.size = size
|
this.size = size
|
||||||
|
@ -24,6 +24,7 @@ class GridCell(
|
|||||||
private val columnConstraint: GridColumnConstraint,
|
private val columnConstraint: GridColumnConstraint,
|
||||||
private val rowConstraint: GridRowConstraint,
|
private val rowConstraint: GridRowConstraint,
|
||||||
private val child: Element,
|
private val child: Element,
|
||||||
|
override var parent: Element?,
|
||||||
) : Element(hudRenderer) {
|
) : Element(hudRenderer) {
|
||||||
override var prepared: Boolean by child::prepared
|
override var prepared: Boolean by child::prepared
|
||||||
override var size: Vec2i by child::size
|
override var size: Vec2i by child::size
|
||||||
|
@ -36,12 +36,7 @@ class GridLayout(hudRenderer: HUDRenderer, val grid: Vec2i) : Layout(hudRenderer
|
|||||||
fun add(position: Vec2i, element: Element) {
|
fun add(position: Vec2i, element: Element) {
|
||||||
children[position.x][position.y]?.parent = null
|
children[position.x][position.y]?.parent = null
|
||||||
|
|
||||||
val cell = GridCell(hudRenderer, columnConstraints[position.x], rowConstraints[position.y], element)
|
val cell = GridCell(hudRenderer, columnConstraints[position.x], rowConstraints[position.y], element, this)
|
||||||
cell.parent = this
|
|
||||||
|
|
||||||
// Apply new maxSize
|
|
||||||
element.apply()
|
|
||||||
element.onParentChange()
|
|
||||||
|
|
||||||
children[position.x][position.y] = cell
|
children[position.x][position.y] = cell
|
||||||
|
|
||||||
@ -110,6 +105,9 @@ class GridLayout(hudRenderer: HUDRenderer, val grid: Vec2i) : Layout(hudRenderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size = Vec2i(width.sum(), 0)
|
||||||
|
|
||||||
// apply the size changes to all children
|
// apply the size changes to all children
|
||||||
applyOnlyChildren()
|
applyOnlyChildren()
|
||||||
|
|
||||||
@ -123,8 +121,6 @@ class GridLayout(hudRenderer: HUDRenderer, val grid: Vec2i) : Layout(hudRenderer
|
|||||||
columnStart[x] = offset + previousWidth
|
columnStart[x] = offset + previousWidth
|
||||||
}
|
}
|
||||||
this.columnStart = columnStart
|
this.columnStart = columnStart
|
||||||
|
|
||||||
size = Vec2i(width.sum(), 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun apply() {
|
override fun apply() {
|
||||||
@ -138,7 +134,7 @@ class GridLayout(hudRenderer: HUDRenderer, val grid: Vec2i) : Layout(hudRenderer
|
|||||||
for (x in 0 until grid.x) {
|
for (x in 0 until grid.x) {
|
||||||
for (y in 0 until grid.y) {
|
for (y in 0 until grid.y) {
|
||||||
val child = children[x][y] ?: continue
|
val child = children[x][y] ?: continue
|
||||||
val childZ = child.render(offset + margin.offset + Vec2i(columnStart[x], rowStart[y]) + columnConstraints[x].alignment.getOffset(columnConstraints[x].width, child.size.x), z, consumer)
|
val childZ = child.render(offset + margin.offset + Vec2i(columnStart[x] + columnConstraints[x].alignment.getOffset(columnConstraints[x].width, child.size.x), rowStart[y]), z, consumer)
|
||||||
if (childZ > maxZ) {
|
if (childZ > maxZ) {
|
||||||
maxZ = childZ
|
maxZ = childZ
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ open class TextElement(
|
|||||||
text: Any,
|
text: Any,
|
||||||
override var fontAlignment: ElementAlignments = ElementAlignments.LEFT,
|
override var fontAlignment: ElementAlignments = ElementAlignments.LEFT,
|
||||||
) : LabeledElement(hudRenderer) {
|
) : LabeledElement(hudRenderer) {
|
||||||
|
private var preparedSize = Vec2i.EMPTY
|
||||||
private var renderInfo = TextRenderInfo()
|
private var renderInfo = TextRenderInfo()
|
||||||
|
|
||||||
override var text: Any = text
|
override var text: Any = text
|
||||||
@ -42,6 +43,9 @@ open class TextElement(
|
|||||||
final override var textComponent: ChatComponent = ChatComponent.of("")
|
final override var textComponent: ChatComponent = ChatComponent.of("")
|
||||||
protected set(value) {
|
protected set(value) {
|
||||||
field = value
|
field = value
|
||||||
|
val prefSize = Vec2i.EMPTY
|
||||||
|
ChatComponentRenderer.render(Vec2i.EMPTY, Vec2i.EMPTY, prefSize, 0, InfiniteSizeElement(hudRenderer), fontAlignment, renderWindow, null, TextRenderInfo(), value)
|
||||||
|
this.prefSize = prefSize
|
||||||
apply()
|
apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,20 +56,16 @@ open class TextElement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun silentApply() {
|
override fun silentApply() {
|
||||||
val text = textComponent
|
|
||||||
size = Vec2i.EMPTY
|
size = Vec2i.EMPTY
|
||||||
if (text.message.isNotEmpty()) {
|
if (textComponent.message.isNotEmpty()) {
|
||||||
val size = Vec2i.EMPTY
|
val size = Vec2i.EMPTY
|
||||||
val renderInfo = TextRenderInfo()
|
val renderInfo = TextRenderInfo()
|
||||||
ChatComponentRenderer.render(Vec2i.EMPTY, Vec2i.EMPTY, size, 0, this, fontAlignment, renderWindow, null, renderInfo, text)
|
ChatComponentRenderer.render(Vec2i.EMPTY, Vec2i.EMPTY, size, 0, this, fontAlignment, renderWindow, null, renderInfo, textComponent)
|
||||||
val prefSize = Vec2i.EMPTY
|
|
||||||
ChatComponentRenderer.render(Vec2i.EMPTY, Vec2i.EMPTY, prefSize, 0, InfiniteSizeElement(hudRenderer), fontAlignment, renderWindow, null, TextRenderInfo(), text)
|
|
||||||
this.prefSize = prefSize
|
|
||||||
|
|
||||||
// ToDo: Set prefSize
|
|
||||||
renderInfo.currentLine = 0
|
renderInfo.currentLine = 0
|
||||||
this.renderInfo = renderInfo
|
this.renderInfo = renderInfo
|
||||||
this.size = size
|
this.size = size
|
||||||
|
preparedSize = size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,13 +77,13 @@ open class TextElement(
|
|||||||
override fun onChildChange(child: Element?) = error("A TextElement can not have a child!")
|
override fun onChildChange(child: Element?) = error("A TextElement can not have a child!")
|
||||||
|
|
||||||
override fun onParentChange() {
|
override fun onParentChange() {
|
||||||
val size = Vec2i(size)
|
|
||||||
val maxSize = maxSize
|
val maxSize = maxSize
|
||||||
|
val prefSize = prefSize
|
||||||
|
|
||||||
if (size.x > maxSize.x) {
|
if (preparedSize.x < prefSize.x || preparedSize.x > maxSize.x) {
|
||||||
return silentApply()
|
return silentApply()
|
||||||
}
|
}
|
||||||
if (size.y > maxSize.y) {
|
if (preparedSize.y < prefSize.y || preparedSize.y > maxSize.y) {
|
||||||
return silentApply()
|
return silentApply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import de.bixilon.minosoft.data.text.ChatColors
|
|||||||
import de.bixilon.minosoft.data.text.TextComponent
|
import de.bixilon.minosoft.data.text.TextComponent
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||||
import de.bixilon.minosoft.gui.rendering.block.WorldRenderer
|
import de.bixilon.minosoft.gui.rendering.block.WorldRenderer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.font.Font
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.elements.ElementAlignments
|
import de.bixilon.minosoft.gui.rendering.gui.elements.ElementAlignments
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.elements.layout.RowLayout
|
import de.bixilon.minosoft.gui.rendering.gui.elements.layout.RowLayout
|
||||||
@ -33,6 +34,7 @@ import de.bixilon.minosoft.terminal.RunConfiguration
|
|||||||
import de.bixilon.minosoft.util.KUtil.format
|
import de.bixilon.minosoft.util.KUtil.format
|
||||||
import de.bixilon.minosoft.util.MMath.round10
|
import de.bixilon.minosoft.util.MMath.round10
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
|
import glm_.vec4.Vec4i
|
||||||
|
|
||||||
class DebugHUD(val hudRenderer: HUDRenderer) : HUD<GridLayout> {
|
class DebugHUD(val hudRenderer: HUDRenderer) : HUD<GridLayout> {
|
||||||
override val renderWindow: RenderWindow = hudRenderer.renderWindow
|
override val renderWindow: RenderWindow = hudRenderer.renderWindow
|
||||||
@ -55,8 +57,8 @@ class DebugHUD(val hudRenderer: HUDRenderer) : HUD<GridLayout> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initLeft(): Element {
|
private fun initLeft(): Element {
|
||||||
val layout = RowLayout(hudRenderer)
|
val layout = RowLayout(hudRenderer, spacing = Font.VERTICAL_SPACING)
|
||||||
// ToDo: layout.margin = Vec4i(5)
|
layout.margin = Vec4i(5)
|
||||||
layout += TextElement(hudRenderer, TextComponent(RunConfiguration.VERSION_STRING, ChatColors.RED))
|
layout += TextElement(hudRenderer, TextComponent(RunConfiguration.VERSION_STRING, ChatColors.RED))
|
||||||
layout += AutoTextElement(hudRenderer, 1) { "FPS ${renderWindow.renderStats.smoothAvgFPS.round10}" }
|
layout += AutoTextElement(hudRenderer, 1) { "FPS ${renderWindow.renderStats.smoothAvgFPS.round10}" }
|
||||||
renderWindow[WorldRenderer]?.apply {
|
renderWindow[WorldRenderer]?.apply {
|
||||||
@ -80,9 +82,9 @@ class DebugHUD(val hudRenderer: HUDRenderer) : HUD<GridLayout> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initRight(): Element {
|
private fun initRight(): Element {
|
||||||
val layout = RowLayout(hudRenderer, ElementAlignments.RIGHT)
|
val layout = RowLayout(hudRenderer, ElementAlignments.RIGHT, Font.VERTICAL_SPACING)
|
||||||
// ToDo: layout.margin = Vec4i(5)
|
layout.margin = Vec4i(5)
|
||||||
layout += TextElement(hudRenderer, "Java\n${Runtime.version()} ${System.getProperty("sun.arch.data.model")}bit", ElementAlignments.RIGHT) // ToDo: Remove \n
|
layout += TextElement(hudRenderer, "Java ${Runtime.version()} ${System.getProperty("sun.arch.data.model")}bit", ElementAlignments.RIGHT)
|
||||||
|
|
||||||
layout += LineSpacerElement(hudRenderer)
|
layout += LineSpacerElement(hudRenderer)
|
||||||
|
|
||||||
@ -92,8 +94,8 @@ class DebugHUD(val hudRenderer: HUDRenderer) : HUD<GridLayout> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
renderWindow.renderSystem.apply {
|
renderWindow.renderSystem.apply {
|
||||||
layout += TextElement(hudRenderer, "GPU $vendorString")
|
layout += TextElement(hudRenderer, "GPU $vendorString", ElementAlignments.RIGHT)
|
||||||
layout += TextElement(hudRenderer, "Version $version")
|
layout += TextElement(hudRenderer, "Version $version", ElementAlignments.RIGHT)
|
||||||
}
|
}
|
||||||
return layout
|
return layout
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ import glm_.vec4.Vec4
|
|||||||
class GUIMesh(
|
class GUIMesh(
|
||||||
renderWindow: RenderWindow,
|
renderWindow: RenderWindow,
|
||||||
val matrix: Mat4,
|
val matrix: Mat4,
|
||||||
) : Mesh(renderWindow, HUDMeshStruct), GUIVertexConsumer {
|
) : Mesh(renderWindow, HUDMeshStruct, initialCacheSize = 40000), GUIVertexConsumer {
|
||||||
|
|
||||||
override fun addVertex(position: Vec2t<*>, z: Int, texture: AbstractTexture, uv: Vec2, tint: RGBColor) {
|
override fun addVertex(position: Vec2t<*>, z: Int, texture: AbstractTexture, uv: Vec2, tint: RGBColor) {
|
||||||
val outPosition = matrix * Vec4(position.x.toFloat(), position.y.toFloat(), 1.0f, 1.0f)
|
val outPosition = matrix * Vec4(position.x.toFloat(), position.y.toFloat(), 1.0f, 1.0f)
|
||||||
|
@ -63,7 +63,7 @@ interface BaseWindow {
|
|||||||
val DEFAULT_WINDOW_SIZE: Vec2i
|
val DEFAULT_WINDOW_SIZE: Vec2i
|
||||||
get() = Vec2i(900, 500)
|
get() = Vec2i(900, 500)
|
||||||
val DEFAULT_MINIMUM_WINDOW_SIZE: Vec2i
|
val DEFAULT_MINIMUM_WINDOW_SIZE: Vec2i
|
||||||
get() = Vec2i(100, 100)
|
get() = Vec2i(300, 100)
|
||||||
val DEFAULT_MAXIMUM_WINDOW_SIZE: Vec2i
|
val DEFAULT_MAXIMUM_WINDOW_SIZE: Vec2i
|
||||||
get() = Vec2i(-1, -1)
|
get() = Vec2i(-1, -1)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user