Mercurial > games > semicongine
changeset 416:73cca428e27a
did: changes
author | Sam <sam@basx.dev> |
---|---|
date | Sat, 27 Jan 2024 21:08:31 +0700 |
parents | 25db1fa56cb7 |
children | b032768df631 |
files | semicongine/text.nim tests/test_font.nim |
diffstat | 2 files changed, 42 insertions(+), 34 deletions(-) [+] |
line wrap: on
line diff
--- a/semicongine/text.nim Sat Jan 27 00:31:11 2024 +0700 +++ b/semicongine/text.nim Sat Jan 27 21:08:31 2024 +0700 @@ -33,17 +33,17 @@ attributes: {"fontAtlas": TextureType, "color": Vec4F32}.toTable, ) TEXT_SHADER* = createShaderConfiguration( - inputs=[ - attr[Mat4](TRANSFORM_ATTRIB, memoryPerformanceHint=PreferFastWrite, perInstance=true), - attr[Vec3f](POSITION_ATTRIB, memoryPerformanceHint=PreferFastWrite), - attr[Vec2f](UV_ATTRIB, memoryPerformanceHint=PreferFastWrite), + inputs = [ + attr[Mat4](TRANSFORM_ATTRIB, memoryPerformanceHint = PreferFastWrite, perInstance = true), + attr[Vec3f](POSITION_ATTRIB, memoryPerformanceHint = PreferFastWrite), + attr[Vec2f](UV_ATTRIB, memoryPerformanceHint = PreferFastWrite), ], - intermediates=[attr[Vec2f]("uvFrag")], - outputs=[attr[Vec4f]("color")], - uniforms=[attr[Vec4f]("color")], - samplers=[attr[Texture]("fontAtlas")], - vertexCode= &"""gl_Position = vec4({POSITION_ATTRIB}, 1.0) * {TRANSFORM_ATTRIB}; uvFrag = {UV_ATTRIB};""", - fragmentCode= &"""color = vec4(Uniforms.color.rgb, Uniforms.color.a * texture(fontAtlas, uvFrag).r);""" + intermediates = [attr[Vec2f]("uvFrag")], + outputs = [attr[Vec4f]("color")], + uniforms = [attr[Vec4f]("color")], + samplers = [attr[Texture]("fontAtlas")], + vertexCode = &"""gl_Position = vec4({POSITION_ATTRIB}, 1.0) * {TRANSFORM_ATTRIB}; uvFrag = {UV_ATTRIB};""", + fragmentCode = &"""color = vec4(Uniforms.color.rgb, Uniforms.color.a * texture(fontAtlas, uvFrag).r);""" ) proc updateMesh(textbox: var Text) = @@ -64,8 +64,9 @@ width += textbox.font.kerning[(textbox.text[i], textbox.text[i + 1])] maxWidth = max(width, maxWidth) - let centerX = maxWidth / 2 - let centerY = height / 2 + let anchorX = maxWidth / 2 + # let anchorY = height / 2 # use this for vertical centering + let anchorY = 0'f32 var offsetX = 0'f32 var offsetY = 0'f32 @@ -84,10 +85,10 @@ top = offsetY + glyph.topOffset bottom = offsetY + glyph.topOffset + glyph.dimension.y - textbox.mesh[POSITION_ATTRIB, vertexOffset + 0] = newVec3f(left - centerX, bottom - centerY) - textbox.mesh[POSITION_ATTRIB, vertexOffset + 1] = newVec3f(left - centerX, top - centerY) - textbox.mesh[POSITION_ATTRIB, vertexOffset + 2] = newVec3f(right - centerX, top - centerY) - textbox.mesh[POSITION_ATTRIB, vertexOffset + 3] = newVec3f(right - centerX, bottom - centerY) + textbox.mesh[POSITION_ATTRIB, vertexOffset + 0] = newVec3f(left - anchorX, bottom - anchorY) + textbox.mesh[POSITION_ATTRIB, vertexOffset + 1] = newVec3f(left - anchorX, top - anchorY) + textbox.mesh[POSITION_ATTRIB, vertexOffset + 2] = newVec3f(right - anchorX, top - anchorY) + textbox.mesh[POSITION_ATTRIB, vertexOffset + 3] = newVec3f(right - anchorX, bottom - anchorY) textbox.mesh[UV_ATTRIB, vertexOffset + 0] = glyph.uvs[0] textbox.mesh[UV_ATTRIB, vertexOffset + 1] = glyph.uvs[1] @@ -108,12 +109,15 @@ textbox.text proc `text=`*(textbox: var Text, text: seq[Rune]) = - textbox.text = text - textbox.updateMesh() + let newText = text[0 ..< min(text.len, textbox.maxLen)] + if textbox.text != newText: + textbox.text = newText + textbox.updateMesh() + proc `text=`*(textbox: var Text, text: string) = `text=`(textbox, text.toRunes) -proc initText*(maxLen: int, font: Font, text="".toRunes, color=newVec4f(0, 0, 0, 1)): Text = +proc initText*(maxLen: int, font: Font, text = "".toRunes, color = newVec4f(0, 0, 0, 1)): Text = var positions = newSeq[Vec3f](int(maxLen * 4)) indices: seq[array[3, uint16]] @@ -131,12 +135,13 @@ result.mesh[].renameAttribute("position", POSITION_ATTRIB) result.mesh[].renameAttribute("uv", UV_ATTRIB) result.mesh.material = initMaterialData( - theType=TEXT_MATERIAL_TYPE, - name=font.name & " text", - attributes={"fontAtlas": initDataList(@[font.fontAtlas]), "color": initDataList(@[color])}, + theType = TEXT_MATERIAL_TYPE, + name = font.name & " text", + attributes = {"fontAtlas": initDataList(@[font.fontAtlas]), + "color": initDataList(@[color])}, ) result.updateMesh() -proc initText*(maxLen: int, font: Font, text="", color=newVec4f(0, 0, 0, 1)): Text = - initText(maxLen=maxLen, font=font, text=text.toRunes, color=color) +proc initText*(maxLen: int, font: Font, text = "", color = newVec4f(0, 0, 0, 1)): Text = + initText(maxLen = maxLen, font = font, text = text.toRunes, color = color)
--- a/tests/test_font.nim Sat Jan 27 00:31:11 2024 +0700 +++ b/tests/test_font.nim Sat Jan 27 21:08:31 2024 +0700 @@ -10,29 +10,32 @@ # build scene var scene = Scene(name: "main") # var font = loadFont("DejaVuSans.ttf", lineHeightPixels=90'f32, charset="abcdefghijklmnopqrstuvwxyz ".toRunes) - var font = loadFont("DejaVuSans.ttf", lineHeightPixels=180'f32) - var textbox = initText(32, font, "", color=newVec4f(1, 0, 0, 1)) - let fontscale = 0.002 + var font = loadFont("DejaVuSans.ttf", lineHeightPixels = 250'f32) + var textbox = initText(32, font, "_", color = newVec4f(1, 0, 0, 1)) + let fontscale = 0.001 scene.add textbox textbox.mesh.transform = scale(fontscale, fontscale) engine.loadScene(scene) + let cursor = Rune('_') while engine.updateInputs() == Running and not engine.keyIsDown(Escape): if engine.windowWasResized(): var winSize = engine.getWindow().size textbox.mesh.transform = scale(fontscale * (winSize[1] / winSize[0]), fontscale) - for c in [Key.A, Key.B, Key.C, Key.D, Key.E, Key.F, Key.G, Key.H, Key.I, Key.J, Key.K, Key.L, Key.M, Key.N, Key.O, Key.P, Key.Q, Key.R, Key.S, Key.T, Key.U, Key.V, Key.W, Key.X, Key.Y, Key.Z]: + for c in [Key.A, Key.B, Key.C, Key.D, Key.E, Key.F, Key.G, Key.H, Key.I, + Key.J, Key.K, Key.L, Key.M, Key.N, Key.O, Key.P, Key.Q, Key.R, Key.S, + Key.T, Key.U, Key.V, Key.W, Key.X, Key.Y, Key.Z]: if engine.keyWasPressed(c): if engine.keyIsDown(ShiftL) or engine.keyIsDown(ShiftR): - textbox.text = textbox.text & ($c).toRunes + textbox.text = textbox.text[0 ..< ^1] & ($c).toRunes & cursor else: - textbox.text = textbox.text & ($c).toRunes[0].toLower() + textbox.text = textbox.text[0 ..< ^1] & ($c).toRunes[0].toLower() & cursor if engine.keyWasPressed(Enter): - textbox.text = textbox.text & Rune('\n') + textbox.text = textbox.text[0 ..< ^1] & Rune('\n') & cursor if engine.keyWasPressed(Space): - textbox.text = textbox.text & Rune(' ') - if engine.keyWasPressed(Backspace) and textbox.text.len > 0: - textbox.text = textbox.text[0 ..< ^1] + textbox.text = textbox.text[0 ..< ^1] & Rune(' ') & cursor + if engine.keyWasPressed(Backspace) and textbox.text.len > 1: + textbox.text = textbox.text[0 ..< ^2] & cursor engine.renderScene(scene) engine.destroy()