Mercurial > games > semicongine
comparison semiconginev2/text/textbox.nim @ 1239:69489a678141
add: better syncing, better swapchain access, correct font offset, two font-rendering tests
author | sam <sam@basx.dev> |
---|---|
date | Mon, 22 Jul 2024 00:46:10 +0700 |
parents | 03634915bbdb |
children | 42eeb59f3a43 |
comparison
equal
deleted
inserted
replaced
1238:03634915bbdb | 1239:69489a678141 |
---|---|
21 | 21 |
22 func `$`*(textbox: Textbox): string = | 22 func `$`*(textbox: Textbox): string = |
23 "\"" & $textbox.text[0 ..< min(textbox.text.len, 16)] & "\"" | 23 "\"" & $textbox.text[0 ..< min(textbox.text.len, 16)] & "\"" |
24 | 24 |
25 proc RefreshShaderdata(textbox: Textbox) = | 25 proc RefreshShaderdata(textbox: Textbox) = |
26 textbox.shaderdata.data.textbox.UpdateGPUBuffer() | 26 textbox.shaderdata.data.textbox.UpdateGPUBuffer(flush = true) |
27 | 27 |
28 proc RefreshGeometry(textbox: var Textbox) = | 28 proc RefreshGeometry(textbox: var Textbox) = |
29 # pre-calculate text-width | 29 # pre-calculate text-width |
30 var width = 0'f32 | 30 var width = 0'f32 |
31 var lineWidths: seq[float32] | 31 var lineWidths: seq[float32] |
43 if lineWidths[^1] == 0 and lineWidths.len > 1: | 43 if lineWidths[^1] == 0 and lineWidths.len > 1: |
44 height -= 1 | 44 height -= 1 |
45 | 45 |
46 let anchorY = (case textbox.verticalAlignment | 46 let anchorY = (case textbox.verticalAlignment |
47 of Top: 0'f32 | 47 of Top: 0'f32 |
48 of Center: height / 2 | 48 of Center: -height / 2 |
49 of Bottom: height) - textbox.font.capHeight | 49 of Bottom: -height |
50 ) - textbox.font.capHeight | |
50 | 51 |
51 var | 52 var |
52 offsetX = 0'f32 | 53 offsetX = 0'f32 |
53 offsetY = 0'f32 | 54 offsetY = 0'f32 |
54 lineIndex = 0 | 55 lineIndex = 0 |
59 for i in 0 ..< textbox.maxLen: | 60 for i in 0 ..< textbox.maxLen: |
60 let vertexOffset = i * 4 | 61 let vertexOffset = i * 4 |
61 if i < textbox.processedText.len: | 62 if i < textbox.processedText.len: |
62 if textbox.processedText[i] == Rune('\n'): | 63 if textbox.processedText[i] == Rune('\n'): |
63 offsetX = 0 | 64 offsetX = 0 |
64 offsetY += textbox.font.lineAdvance | 65 offsetY -= textbox.font.lineAdvance |
65 textbox.position.data[vertexOffset + 0] = NewVec3f() | 66 textbox.position.data[vertexOffset + 0] = NewVec3f() |
66 textbox.position.data[vertexOffset + 1] = NewVec3f() | 67 textbox.position.data[vertexOffset + 1] = NewVec3f() |
67 textbox.position.data[vertexOffset + 2] = NewVec3f() | 68 textbox.position.data[vertexOffset + 2] = NewVec3f() |
68 textbox.position.data[vertexOffset + 3] = NewVec3f() | 69 textbox.position.data[vertexOffset + 3] = NewVec3f() |
69 inc lineIndex | 70 inc lineIndex |
74 else: | 75 else: |
75 let | 76 let |
76 glyph = textbox.font.glyphs[textbox.processedText[i]] | 77 glyph = textbox.font.glyphs[textbox.processedText[i]] |
77 left = offsetX + glyph.leftOffset | 78 left = offsetX + glyph.leftOffset |
78 right = offsetX + glyph.leftOffset + glyph.dimension.x | 79 right = offsetX + glyph.leftOffset + glyph.dimension.x |
79 top = offsetY + glyph.topOffset | 80 top = offsetY - glyph.topOffset |
80 bottom = offsetY + glyph.topOffset + glyph.dimension.y | 81 bottom = offsetY - glyph.topOffset - glyph.dimension.y |
81 | 82 |
82 textbox.position.data[vertexOffset + 1] = NewVec3f(left - anchorX, bottom - anchorY) | 83 textbox.position.data[vertexOffset + 0] = NewVec3f(left - anchorX, bottom - anchorY) |
83 textbox.position.data[vertexOffset + 0] = NewVec3f(left - anchorX, top - anchorY) | 84 textbox.position.data[vertexOffset + 1] = NewVec3f(left - anchorX, top - anchorY) |
84 textbox.position.data[vertexOffset + 3] = NewVec3f(right - anchorX, top - anchorY) | 85 textbox.position.data[vertexOffset + 2] = NewVec3f(right - anchorX, top - anchorY) |
85 textbox.position.data[vertexOffset + 2] = NewVec3f(right - anchorX, bottom - anchorY) | 86 textbox.position.data[vertexOffset + 3] = NewVec3f(right - anchorX, bottom - anchorY) |
86 | 87 |
87 textbox.uv.data[vertexOffset + 0] = glyph.uvs[0] | 88 textbox.uv.data[vertexOffset + 0] = glyph.uvs[0] |
88 textbox.uv.data[vertexOffset + 1] = glyph.uvs[1] | 89 textbox.uv.data[vertexOffset + 1] = glyph.uvs[1] |
89 textbox.uv.data[vertexOffset + 2] = glyph.uvs[2] | 90 textbox.uv.data[vertexOffset + 2] = glyph.uvs[2] |
90 textbox.uv.data[vertexOffset + 3] = glyph.uvs[3] | 91 textbox.uv.data[vertexOffset + 3] = glyph.uvs[3] |
95 else: | 96 else: |
96 textbox.position.data[vertexOffset + 0] = NewVec3f() | 97 textbox.position.data[vertexOffset + 0] = NewVec3f() |
97 textbox.position.data[vertexOffset + 1] = NewVec3f() | 98 textbox.position.data[vertexOffset + 1] = NewVec3f() |
98 textbox.position.data[vertexOffset + 2] = NewVec3f() | 99 textbox.position.data[vertexOffset + 2] = NewVec3f() |
99 textbox.position.data[vertexOffset + 3] = NewVec3f() | 100 textbox.position.data[vertexOffset + 3] = NewVec3f() |
100 UpdateGPUBuffer(textbox.position, flush = true) | 101 UpdateGPUBuffer(textbox.position) |
101 UpdateGPUBuffer(textbox.uv, flush = true) | 102 UpdateGPUBuffer(textbox.uv) |
102 textbox.lastRenderedText = textbox.processedText | 103 textbox.lastRenderedText = textbox.processedText |
103 | 104 |
104 func text*(textbox: Textbox): seq[Rune] = | 105 func text*(textbox: Textbox): seq[Rune] = |
105 textbox.text | 106 textbox.text |
106 | 107 |
135 proc `Scale=`*(textbox: var Textbox, value: float32) = | 136 proc `Scale=`*(textbox: var Textbox, value: float32) = |
136 if textbox.shaderdata.data.textbox.data.scale != value: | 137 if textbox.shaderdata.data.textbox.data.scale != value: |
137 textbox.dirtyShaderdata = true | 138 textbox.dirtyShaderdata = true |
138 textbox.shaderdata.data.textbox.data.scale = value | 139 textbox.shaderdata.data.textbox.data.scale = value |
139 | 140 |
140 proc AspectRatio*(textbox: Textbox): float32 = | |
141 textbox.shaderdata.data.textbox.data.aspectratio | |
142 | |
143 proc `AspectRatio=`*(textbox: var Textbox, value: float32) = | |
144 if textbox.shaderdata.data.textbox.data.aspectratio != value: | |
145 textbox.dirtyShaderdata = true | |
146 textbox.shaderdata.data.textbox.data.aspectratio = value | |
147 | |
148 proc Position*(textbox: Textbox): Vec3f = | 141 proc Position*(textbox: Textbox): Vec3f = |
149 textbox.shaderdata.data.textbox.data.position | 142 textbox.shaderdata.data.textbox.data.position |
150 | 143 |
151 proc `Position=`*(textbox: var Textbox, value: Vec3f) = | 144 proc `Position=`*(textbox: var Textbox, value: Vec3f) = |
152 if textbox.shaderdata.data.textbox.data.position != value: | 145 if textbox.shaderdata.data.textbox.data.position != value: |
165 proc `verticalAlignment=`*(textbox: var Textbox, value: VerticalAlignment) = | 158 proc `verticalAlignment=`*(textbox: var Textbox, value: VerticalAlignment) = |
166 if value != textbox.verticalAlignment: | 159 if value != textbox.verticalAlignment: |
167 textbox.verticalAlignment = value | 160 textbox.verticalAlignment = value |
168 textbox.dirtyGeometry = true | 161 textbox.dirtyGeometry = true |
169 | 162 |
170 proc Refresh*(textbox: var Textbox, aspectratio: float32) = | 163 proc Refresh*(textbox: var Textbox) = |
171 `AspectRatio=`(textbox, aspectratio) | 164 if textbox.shaderdata.data.textbox.data.aspectratio != GetAspectRatio(): |
165 textbox.dirtyShaderdata = true | |
166 textbox.shaderdata.data.textbox.data.aspectratio = GetAspectRatio() | |
172 | 167 |
173 if textbox.dirtyShaderdata: | 168 if textbox.dirtyShaderdata: |
174 textbox.RefreshShaderdata() | 169 textbox.RefreshShaderdata() |
175 textbox.dirtyShaderdata = false | 170 textbox.dirtyShaderdata = false |
176 | 171 |
177 if textbox.dirtyGeometry or textbox.processedText != textbox.lastRenderedText: | 172 if textbox.dirtyGeometry or textbox.processedText != textbox.lastRenderedText: |
178 textbox.RefreshGeometry() | 173 textbox.RefreshGeometry() |
179 textbox.dirtyGeometry = false | 174 textbox.dirtyGeometry = false |
180 | 175 |
181 proc Render*(textbox: Textbox, commandbuffer: VkCommandBuffer, pipeline: Pipeline, currentFiF: int) = | 176 proc Render*(textbox: Textbox, commandbuffer: VkCommandBuffer, pipeline: Pipeline) = |
182 WithBind(commandbuffer, (textbox.shaderdata, ), pipeline, currentFiF): | 177 WithBind(commandbuffer, (textbox.shaderdata, ), pipeline): |
183 Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = textbox) | 178 Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = textbox) |
184 | 179 |
185 proc InitTextbox*[T: string | seq[Rune]]( | 180 proc InitTextbox*[T: string | seq[Rune]]( |
186 renderdata: var RenderData, | 181 renderdata: var RenderData, |
187 descriptorSetLayout: VkDescriptorSetLayout, | 182 descriptorSetLayout: VkDescriptorSetLayout, |
236 | 231 |
237 AssignBuffers(renderdata, result, uploadData = false) | 232 AssignBuffers(renderdata, result, uploadData = false) |
238 UploadImages(renderdata, result.shaderdata) | 233 UploadImages(renderdata, result.shaderdata) |
239 InitDescriptorSet(renderdata, descriptorSetLayout, result.shaderdata) | 234 InitDescriptorSet(renderdata, descriptorSetLayout, result.shaderdata) |
240 | 235 |
241 result.Refresh(1) | 236 result.Refresh() |
242 UpdateAllGPUBuffers(result, flush = true) | 237 UpdateAllGPUBuffers(result, flush = true, allFrames = true) |
243 UpdateAllGPUBuffers(result.shaderdata.data, flush = true) | 238 UpdateAllGPUBuffers(result.shaderdata.data, flush = true) |