Mercurial > games > semicongine
annotate semicongine/text.nim @ 878:8ab77af322cc
add: alignment for text boxes
author | Sam <sam@basx.dev> |
---|---|
date | Sun, 28 Jan 2024 00:41:11 +0700 |
parents | 773af36148bd |
children | 7ecae083b670 |
rev | line source |
---|---|
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
1 import std/tables |
878 | 2 # import std/sequtils |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
3 import std/unicode |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
4 import std/strformat |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
5 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
6 import ./core |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
7 import ./mesh |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
8 import ./material |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
9 import ./vulkan/shader |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
10 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
11 const SHADER_ATTRIB_PREFIX = "semicon_text_" |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
12 var instanceCounter = 0 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
13 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
14 type |
878 | 15 HorizontalAlignment = enum |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
16 Left |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
17 Center |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
18 Right |
878 | 19 VerticalAlignment = enum |
20 Top | |
21 Center | |
22 Bottom | |
872
1ee397815b0b
did: image & font refactoring, add texture-atlas-packing
Sam <sam@basx.dev>
parents:
868
diff
changeset
|
23 Text* = object |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
24 maxLen*: int |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
25 text: seq[Rune] |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
26 dirty: bool |
878 | 27 horizontalAlignment*: HorizontalAlignment = Center |
28 verticalAlignment*: VerticalAlignment = Center | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
29 font*: Font |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
30 mesh*: Mesh |
872
1ee397815b0b
did: image & font refactoring, add texture-atlas-packing
Sam <sam@basx.dev>
parents:
868
diff
changeset
|
31 color*: Vec4f |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
32 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
33 const |
878 | 34 NEWLINE = Rune('\n') |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
35 POSITION_ATTRIB = SHADER_ATTRIB_PREFIX & "position" |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
36 UV_ATTRIB = SHADER_ATTRIB_PREFIX & "uv" |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
37 TEXT_MATERIAL_TYPE* = MaterialType( |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
38 name: "default-text-material-type", |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
39 vertexAttributes: {TRANSFORM_ATTRIB: Mat4F32, POSITION_ATTRIB: Vec3F32, UV_ATTRIB: Vec2F32}.toTable, |
872
1ee397815b0b
did: image & font refactoring, add texture-atlas-packing
Sam <sam@basx.dev>
parents:
868
diff
changeset
|
40 attributes: {"fontAtlas": TextureType, "color": Vec4F32}.toTable, |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
41 ) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
42 TEXT_SHADER* = createShaderConfiguration( |
877 | 43 inputs = [ |
44 attr[Mat4](TRANSFORM_ATTRIB, memoryPerformanceHint = PreferFastWrite, perInstance = true), | |
45 attr[Vec3f](POSITION_ATTRIB, memoryPerformanceHint = PreferFastWrite), | |
46 attr[Vec2f](UV_ATTRIB, memoryPerformanceHint = PreferFastWrite), | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
47 ], |
877 | 48 intermediates = [attr[Vec2f]("uvFrag")], |
49 outputs = [attr[Vec4f]("color")], | |
50 uniforms = [attr[Vec4f]("color")], | |
51 samplers = [attr[Texture]("fontAtlas")], | |
52 vertexCode = &"""gl_Position = vec4({POSITION_ATTRIB}, 1.0) * {TRANSFORM_ATTRIB}; uvFrag = {UV_ATTRIB};""", | |
53 fragmentCode = &"""color = vec4(Uniforms.color.rgb, Uniforms.color.a * texture(fontAtlas, uvFrag).r);""" | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
54 ) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
55 |
872
1ee397815b0b
did: image & font refactoring, add texture-atlas-packing
Sam <sam@basx.dev>
parents:
868
diff
changeset
|
56 proc updateMesh(textbox: var Text) = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
57 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
58 # pre-calculate text-width |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
59 var width = 0'f32 |
878 | 60 var lineWidths: seq[float32] |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
61 for i in 0 ..< min(textbox.text.len, textbox.maxLen): |
878 | 62 if textbox.text[i] == NEWLINE: |
63 lineWidths.add width | |
872
1ee397815b0b
did: image & font refactoring, add texture-atlas-packing
Sam <sam@basx.dev>
parents:
868
diff
changeset
|
64 width = 0'f32 |
876
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
65 else: |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
66 width += textbox.font.glyphs[textbox.text[i]].advance |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
67 if i < textbox.text.len - 1: |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
68 width += textbox.font.kerning[(textbox.text[i], textbox.text[i + 1])] |
878 | 69 lineWidths.add width |
70 let | |
71 height = float32(lineWidths.len) * textbox.font.lineAdvance | |
72 | |
73 let anchorY = (case textbox.verticalAlignment | |
74 of Top: 0'f32 | |
75 of Center: height / 2 | |
76 of Bottom: height) - textbox.font.lineAdvance | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
77 |
878 | 78 var |
79 offsetX = 0'f32 | |
80 offsetY = 0'f32 | |
81 lineIndex = 0 | |
82 anchorX = case textbox.horizontalAlignment | |
83 of Left: 0'f32 | |
84 of Center: lineWidths[lineIndex] / 2 | |
85 of Right: lineWidths.max | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
86 for i in 0 ..< textbox.maxLen: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
87 let vertexOffset = i * 4 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
88 if i < textbox.text.len: |
876
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
89 if textbox.text[i] == Rune('\n'): |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
90 offsetX = 0 |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
91 offsetY += textbox.font.lineAdvance |
878 | 92 textbox.mesh[POSITION_ATTRIB, vertexOffset + 0] = newVec3f() |
93 textbox.mesh[POSITION_ATTRIB, vertexOffset + 1] = newVec3f() | |
94 textbox.mesh[POSITION_ATTRIB, vertexOffset + 2] = newVec3f() | |
95 textbox.mesh[POSITION_ATTRIB, vertexOffset + 3] = newVec3f() | |
96 inc lineIndex | |
97 anchorX = case textbox.horizontalAlignment | |
98 of Left: 0'f32 | |
99 of Center: lineWidths[lineIndex] / 2 | |
100 of Right: lineWidths.max | |
876
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
101 else: |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
102 let |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
103 glyph = textbox.font.glyphs[textbox.text[i]] |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
104 left = offsetX + glyph.leftOffset |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
105 right = offsetX + glyph.leftOffset + glyph.dimension.x |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
106 top = offsetY + glyph.topOffset |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
107 bottom = offsetY + glyph.topOffset + glyph.dimension.y |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
108 |
877 | 109 textbox.mesh[POSITION_ATTRIB, vertexOffset + 0] = newVec3f(left - anchorX, bottom - anchorY) |
110 textbox.mesh[POSITION_ATTRIB, vertexOffset + 1] = newVec3f(left - anchorX, top - anchorY) | |
111 textbox.mesh[POSITION_ATTRIB, vertexOffset + 2] = newVec3f(right - anchorX, top - anchorY) | |
112 textbox.mesh[POSITION_ATTRIB, vertexOffset + 3] = newVec3f(right - anchorX, bottom - anchorY) | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
113 |
876
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
114 textbox.mesh[UV_ATTRIB, vertexOffset + 0] = glyph.uvs[0] |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
115 textbox.mesh[UV_ATTRIB, vertexOffset + 1] = glyph.uvs[1] |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
116 textbox.mesh[UV_ATTRIB, vertexOffset + 2] = glyph.uvs[2] |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
117 textbox.mesh[UV_ATTRIB, vertexOffset + 3] = glyph.uvs[3] |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
118 |
876
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
119 offsetX += glyph.advance |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
120 if i < textbox.text.len - 1: |
164b41a2d5a6
add: font/text improvments, support for newline rendering
Sam <sam@basx.dev>
parents:
872
diff
changeset
|
121 offsetX += textbox.font.kerning[(textbox.text[i], textbox.text[i + 1])] |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
122 else: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
123 textbox.mesh[POSITION_ATTRIB, vertexOffset + 0] = newVec3f() |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
124 textbox.mesh[POSITION_ATTRIB, vertexOffset + 1] = newVec3f() |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
125 textbox.mesh[POSITION_ATTRIB, vertexOffset + 2] = newVec3f() |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
126 textbox.mesh[POSITION_ATTRIB, vertexOffset + 3] = newVec3f() |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
127 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
128 |
872
1ee397815b0b
did: image & font refactoring, add texture-atlas-packing
Sam <sam@basx.dev>
parents:
868
diff
changeset
|
129 func text*(textbox: Text): seq[Rune] = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
130 textbox.text |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
131 |
872
1ee397815b0b
did: image & font refactoring, add texture-atlas-packing
Sam <sam@basx.dev>
parents:
868
diff
changeset
|
132 proc `text=`*(textbox: var Text, text: seq[Rune]) = |
877 | 133 let newText = text[0 ..< min(text.len, textbox.maxLen)] |
134 if textbox.text != newText: | |
135 textbox.text = newText | |
136 textbox.updateMesh() | |
137 | |
872
1ee397815b0b
did: image & font refactoring, add texture-atlas-packing
Sam <sam@basx.dev>
parents:
868
diff
changeset
|
138 proc `text=`*(textbox: var Text, text: string) = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
139 `text=`(textbox, text.toRunes) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
140 |
878 | 141 proc horizontalAlignment*(textbox: Text): HorizontalAlignment = |
142 textbox.horizontalAlignment | |
143 proc verticalAlignment*(textbox: Text): VerticalAlignment = | |
144 textbox.verticalAlignment | |
145 proc `horizontalAlignment=`*(textbox: var Text, value: HorizontalAlignment) = | |
146 if value != textbox.horizontalAlignment: | |
147 textbox.horizontalAlignment = value | |
148 textbox.updateMesh() | |
149 proc `verticalAlignment=`*(textbox: var Text, value: VerticalAlignment) = | |
150 if value != textbox.verticalAlignment : | |
151 textbox.verticalAlignment = value | |
152 textbox.updateMesh() | |
153 | |
154 | |
877 | 155 proc initText*(maxLen: int, font: Font, text = "".toRunes, color = newVec4f(0, 0, 0, 1)): Text = |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
156 var |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
157 positions = newSeq[Vec3f](int(maxLen * 4)) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
158 indices: seq[array[3, uint16]] |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
159 uvs = newSeq[Vec2f](int(maxLen * 4)) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
160 for i in 0 ..< maxLen: |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
161 let offset = i * 4 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
162 indices.add [ |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
163 [uint16(offset + 0), uint16(offset + 1), uint16(offset + 2)], |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
164 [uint16(offset + 2), uint16(offset + 3), uint16(offset + 0)], |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
165 ] |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
166 |
872
1ee397815b0b
did: image & font refactoring, add texture-atlas-packing
Sam <sam@basx.dev>
parents:
868
diff
changeset
|
167 result = Text(maxLen: maxLen, text: text, font: font, dirty: true) |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
168 result.mesh = newMesh(positions = positions, indices = indices, uvs = uvs, name = &"textbox-{instanceCounter}") |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
169 inc instanceCounter |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
170 result.mesh[].renameAttribute("position", POSITION_ATTRIB) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
171 result.mesh[].renameAttribute("uv", UV_ATTRIB) |
868
252cbc10b25f
did: improve/refactor some of the material API
Sam <sam@basx.dev>
parents:
840
diff
changeset
|
172 result.mesh.material = initMaterialData( |
877 | 173 theType = TEXT_MATERIAL_TYPE, |
174 name = font.name & " text", | |
175 attributes = {"fontAtlas": initDataList(@[font.fontAtlas]), | |
176 "color": initDataList(@[color])}, | |
840
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
177 ) |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
178 |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
179 result.updateMesh() |
44ec744fbedc
did: package restructuring according to nimble recommendation for libraries
Sam <sam@basx.dev>
parents:
diff
changeset
|
180 |
877 | 181 proc initText*(maxLen: int, font: Font, text = "", color = newVec4f(0, 0, 0, 1)): Text = |
182 initText(maxLen = maxLen, font = font, text = text.toRunes, color = color) |