diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt index cca1ef7e..878f351e 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt @@ -15,9 +15,7 @@ import ru.dbotthepony.kstarbound.freetype.FreeType import ru.dbotthepony.kstarbound.freetype.LoadFlag import ru.dbotthepony.kstarbound.gl.* import ru.dbotthepony.kstarbound.math.* -import ru.dbotthepony.kstarbound.render.Camera -import ru.dbotthepony.kstarbound.render.ChunkRenderer -import ru.dbotthepony.kstarbound.render.TileRenderer +import ru.dbotthepony.kstarbound.render.* import ru.dbotthepony.kstarbound.world.CHUNK_SIZE import ru.dbotthepony.kstarbound.world.CHUNK_SIZE_FF import ru.dbotthepony.kstarbound.world.ChunkTile @@ -212,7 +210,7 @@ private fun loop() { state.matrixStack.clear(viewportMatrixGUI.toMutableMatrix()) state.matrixStack.translateWithScale(z = 10f, y = 0f) - state.font.render("FPS: %.2f".format(framesPerSecond)) + state.font.render("FPS: %.2f".format(framesPerSecond), y = 0f, scale = 0.5f) glfwSwapBuffers(window) // swap the color buffers diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/render/Font.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/render/Font.kt index 958f52ef..857b9111 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/render/Font.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/render/Font.kt @@ -23,7 +23,7 @@ private fun breakLines(text: String): List { if (nextLineBreak == previousLineBreak) { list.add("") } else { - list.add(text.substring(previousLineBreak, nextLineBreak - 1)) + list.add(text.substring(previousLineBreak, nextLineBreak)) } if (text.length - 1 <= nextLineBreak) { @@ -43,6 +43,14 @@ private fun breakLines(text: String): List { data class TextSize(val width: Float, val height: Float) +enum class TextAlignX { + LEFT, CENTER, RIGHT +} + +enum class TextAlignY { + TOP, CENTER, BOTTOM +} + class Font( val state: GLStateTracker, val font: String = "./unpacked_assets/hobo.ttf", @@ -72,11 +80,28 @@ class Font( x: Float = 0f, y: Float = 0f, + alignX: TextAlignX = TextAlignX.LEFT, + alignY: TextAlignY = TextAlignY.TOP, + scale: Float = 1f, stack: Matrix4fStack = state.matrixStack, ): TextSize { + if (text.isEmpty()) + return TextSize(0f, 0f) + else if (text.size == 1 && text[0] == "") + return TextSize(0f, lineHeight * scale) + + val totalSize = size(text) + val totalX = totalSize.width * scale + val totalY = totalSize.height * scale + stack.push() - stack.translateWithScale(x = x, y = lineHeight + y) + + when (alignY) { + TextAlignY.TOP -> stack.translateWithScale(x = x, y = lineHeight * scale + y) + TextAlignY.CENTER -> stack.translateWithScale(x = x, y = lineHeight * scale - totalY / 2f + y) + TextAlignY.BOTTOM -> stack.translateWithScale(x = x, y = lineHeight * scale - totalY + y) + } if (scale != 1f) stack.scale(x = scale, y = scale) @@ -87,9 +112,29 @@ class Font( val space = getGlyph(' ') var advancedX = 0f - var advancedY = 0f for (line in text) { + if (line == "") { + stack.translateWithScale(y = lineHeight) + continue + } + + var movedX = 0f + + when (alignX) { + TextAlignX.LEFT -> {} + + TextAlignX.CENTER -> { + movedX = totalX / 2f - lineWidth(line, space) / 2f + stack.translateWithScale(x = movedX) + } + + TextAlignX.RIGHT -> { + movedX = totalX - lineWidth(line, space) + stack.translateWithScale(x = movedX) + } + } + var lineGlyphs = 0 var lineWidth = 0f @@ -114,14 +159,13 @@ class Font( } advancedX = advancedX.coerceAtLeast(lineWidth) - stack.translateWithScale(x = -lineWidth, y = lineHeight) - advancedY += lineHeight + stack.translateWithScale(x = -lineWidth - movedX, y = lineHeight) } state.VAO = null stack.pop() - return TextSize(advancedX * scale, advancedY * scale) + return totalSize } fun render( @@ -130,10 +174,38 @@ class Font( x: Float = 0f, y: Float = 0f, + alignX: TextAlignX = TextAlignX.LEFT, + alignY: TextAlignY = TextAlignY.TOP, + scale: Float = 1f, stack: Matrix4fStack = state.matrixStack, ): TextSize { - return render(breakLines(text), x, y, scale, stack) + return render(breakLines(text), x, y, alignX, alignY, scale, stack) + } + + private fun lineWidth(line: String, space: Glyph): Float { + var lineWidth = 0f + var lineGlyphs = 0 + + for (chr in line) { + if (chr == '\t') { + if (lineGlyphs % 4 == 0) { + lineWidth += space.advanceX * 4 + state.matrixStack.translateWithScale(x = space.advanceX * 4) + } else { + lineWidth += space.advanceX * (lineGlyphs % 4) + state.matrixStack.translateWithScale(x = space.advanceX * (lineGlyphs % 4)) + } + + lineGlyphs += lineGlyphs % 4 + continue + } + + lineWidth += getGlyph(chr).advanceX + lineGlyphs++ + } + + return lineWidth } fun size(lines: List): TextSize { @@ -143,28 +215,7 @@ class Font( val space = getGlyph(' ') for (line in lines) { - var lineWidth = 0f - var lineGlyphs = 0 - - for (chr in line) { - if (chr == '\t') { - if (lineGlyphs % 4 == 0) { - advancedX += space.advanceX * 4 - state.matrixStack.translateWithScale(x = space.advanceX * 4) - } else { - advancedX += space.advanceX * (lineGlyphs % 4) - state.matrixStack.translateWithScale(x = space.advanceX * (lineGlyphs % 4)) - } - - lineGlyphs += lineGlyphs % 4 - continue - } - - lineWidth += getGlyph(chr).advanceX - lineGlyphs++ - } - - advancedX = advancedX.coerceAtLeast(lineWidth) + advancedX = advancedX.coerceAtLeast(lineWidth(line, space)) advancedY += lineHeight }