hud: improve new lines in HUDTextElement.kt

This commit is contained in:
Lukas 2021-06-30 22:56:02 +02:00
parent 8058aeccdc
commit 0177e4533d
2 changed files with 59 additions and 70 deletions

View File

@ -26,8 +26,8 @@ class HUDElementPosition(
}
fun init() {
if (parentElement == null) {
parentElement = parentName?.let { Minosoft.getConfig().config.game.hud.elements[ResourceLocation(it)] }
if (parentElement == null && parentName != null) {
parentElement = Minosoft.getConfig().config.game.hud.elements[ResourceLocation(parentName)]
}
}

View File

@ -19,7 +19,6 @@ import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.TextComponent
import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.hud.HUDMenus
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.elements.position.HUDElementPositionAnchors
import de.bixilon.minosoft.gui.rendering.hud.elements.position.HUDElementPositionUnits
import de.bixilon.minosoft.gui.rendering.hud.elements.position.HUDElementVec2
@ -49,72 +48,19 @@ class HUDTextElement : HUDElement {
alignment = HUDElementPositionAnchors.TOP_LEFT
}
fun renderChatComponent(chatComponent: ChatComponent) {
private fun renderChatComponent(chatComponent: ChatComponent) {
val chars = chatComponent.message.toCharArray()
elements.clear()
val newLinePositions = addCharsWithoutLineBreaks(chars)
insertOverflowLineBreaks(newLinePositions)
val newLinePositions = addChars(chars)
adjustPositionsForLineBreaks(newLinePositions)
}
private fun adjustPositionsForLineBreaks(newLinePositions: MutableList<Int>) {
var currentYPosition = getPositionAtAnchor(HUDElementPositionAnchors.TOP_LEFT).y
for (i in newLinePositions) {
val element = elements[i]
val maxRight = glm.min(hudRenderer.renderWindow.screenDimensions.x, getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x + size.getRealVector(hudRenderer).x)
element.position = when (alignment) {
HUDElementPositionAnchors.TOP_LEFT -> {
currentYPosition += ((Font.CHAR_HEIGHT + 1) * Minosoft.getConfig().config.game.hud.scale).toInt()
HUDElementPosition(HUDElementVec2(Vec2(getPositionAtAnchor(HUDElementPositionAnchors.TOP_LEFT).x, currentYPosition), HUDElementPositionUnits.PIXELS), HUDElementPositionAnchors.TOP_LEFT)
}
HUDElementPositionAnchors.BOTTOM_RIGHT -> {
val xPosition = if (i == 0) {
getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_LEFT).x + maxRight - element.getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x
} else {
getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_LEFT).x + maxRight -
elements[newLinePositions[newLinePositions.indexOf(i)]].getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x
}
HUDElementPosition(HUDElementVec2(Vec2(0, 100), // TODO: y position alignment getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_LEFT).y -
HUDElementPositionUnits.PIXELS), HUDElementPositionAnchors.BOTTOM_LEFT, this, HUDElementPositionAnchors.TOP_LEFT)
}
else -> TODO()
}
}
}
private fun insertOverflowLineBreaks(newLinePositions: MutableList<Int>) {
for (i in 0 until elements.size) {
val element = elements[i]
val elementRight = element.getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x
val maxRight = glm.min(hudRenderer.renderWindow.screenDimensions.x, getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x + size.getRealVector(hudRenderer).x)
val relevantElement = if (i in newLinePositions) {
element
} else {
elements[getLastSpacerElementPosition(i)]
}
if (elementRight > maxRight) {
newLinePositions += i
relevantElement.position = HUDElementPosition(HUDElementVec2(getPositionAtAnchor(HUDElementPositionAnchors.TOP_LEFT).toVec2, HUDElementPositionUnits.PIXELS), HUDElementPositionAnchors.BOTTOM_LEFT)
}
}
}
private fun getLastSpacerElementPosition(position: Int): Int {
for (i in 0..position) {
val j = position - i
if (elements[j] is HUDSpacerElement) {
return j + 1
}
}
return position
}
private fun addCharsWithoutLineBreaks(chars: CharArray): MutableList<Int> {
private fun addChars(chars: CharArray): MutableList<Int> {
var lastElement: HUDElement? = null
val newLinePositions = mutableListOf<Int>()
for (i in chars.indices) {
val char = chars[i]
val maxRight = getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x
val bottomLeftPosition = getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_LEFT).toVec2
for (char in chars) {
if (char in ProtocolDefinition.LINE_BREAK_CHARS) {
lastElement = null
continue
@ -123,7 +69,7 @@ class HUDTextElement : HUDElement {
val elementPosition = lastElement?.let {
HUDElementPosition(BETWEEN_CHARS_OFFSET, HUDElementPositionAnchors.BOTTOM_LEFT, it, HUDElementPositionAnchors.BOTTOM_RIGHT)
} ?: run {
newLinePositions += i
newLinePositions += elements.size
HUDElementPosition(HUDElementVec2(getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_LEFT).toVec2, HUDElementPositionUnits.PIXELS), HUDElementPositionAnchors.BOTTOM_LEFT)
}
val elementSize = HUDElementVec2(fontChar.size.toVec2, HUDElementPositionUnits.SCALED_PIXELS)
@ -132,18 +78,61 @@ class HUDTextElement : HUDElement {
} else {
HUDImageElement(elementPosition, elementSize, z, fontChar)
}
lastElement = newElement
elements += newElement
newElement.init(hudRenderer)
elements.add(newElement)
val elementRight = newElement.getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x
lastElement = newElement
if (elementRight > maxRight) {
val relevantIndex = getLastSpacerElementPosition(elements.lastIndex)
if (elements[relevantIndex] is HUDSpacerElement) {
elements.removeAt(relevantIndex)
}
newLinePositions += relevantIndex
elements[relevantIndex].position = HUDElementPosition(HUDElementVec2(bottomLeftPosition, HUDElementPositionUnits.PIXELS), HUDElementPositionAnchors.BOTTOM_LEFT)
}
}
newLinePositions += elements.size
return newLinePositions
}
override fun init(hudRenderer: HUDRenderer) {
super.init(hudRenderer)
renderChatComponent(TextComponent(contents))
for (element in elements) {
element.init(hudRenderer)
private fun getLastSpacerElementPosition(position: Int): Int {
for (i in 0..position) {
val j = position - i - 1
if (j == 0) {
return position
}
if (elements[j] is HUDSpacerElement) {
return j
}
if (elements[j].position.parentElement == null) {
return j
}
}
return position
}
private fun adjustPositionsForLineBreaks(newLinePositions: MutableList<Int>) {
var currentYPosition = when (alignment) {
HUDElementPositionAnchors.TOP_LEFT -> getPositionAtAnchor(HUDElementPositionAnchors.TOP_LEFT).y
HUDElementPositionAnchors.BOTTOM_RIGHT -> getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).y - (newLinePositions.size-2) * (Font.CHAR_HEIGHT+1) * Minosoft.getConfig().config.game.hud.scale.toInt()
else -> TODO()
}
val left = getPositionAtAnchor(HUDElementPositionAnchors.TOP_LEFT).x
val maxRight = glm.min(hudRenderer.renderWindow.screenDimensions.x, getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x)
for (i in 0 until newLinePositions.size-1) {
val element = elements[newLinePositions[i]]
when (alignment) {
HUDElementPositionAnchors.TOP_LEFT -> {
element.position = HUDElementPosition(HUDElementVec2(Vec2(getPositionAtAnchor(HUDElementPositionAnchors.TOP_LEFT).x, currentYPosition), HUDElementPositionUnits.PIXELS), HUDElementPositionAnchors.TOP_LEFT)
}
HUDElementPositionAnchors.BOTTOM_RIGHT -> {
val elementIndex = newLinePositions[i+1] - 1
val xPosition = left + maxRight - elements[elementIndex].getPositionAtAnchor(HUDElementPositionAnchors.BOTTOM_RIGHT).x
element.position = HUDElementPosition(HUDElementVec2(Vec2(xPosition, currentYPosition), HUDElementPositionUnits.PIXELS), HUDElementPositionAnchors.BOTTOM_LEFT)
}
else -> TODO()
}
currentYPosition += ((Font.CHAR_HEIGHT + 1) * Minosoft.getConfig().config.game.hud.scale).toInt()
}
}