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)