changeset 422:a03b6db25282

add: text-wrapping, fix: incorrect descriptor poolsizes
author Sam <sam@basx.dev>
date Wed, 31 Jan 2024 00:29:40 +0700
parents cc6a67473a52
children 50a2dc75b5bd
files semicongine/renderer.nim semicongine/text.nim tests/test_font.nim
diffstat 3 files changed, 37 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/semicongine/renderer.nim	Mon Jan 29 00:21:16 2024 +0700
+++ b/semicongine/renderer.nim	Wed Jan 31 00:29:40 2024 +0700
@@ -293,14 +293,13 @@
               preferVRAM = true,
             )
 
-        # setup descriptors
+        # TODO: rework the whole descriptor/pool/layout stuff, a bit unclear
         var poolsizes = @[(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, renderer.swapchain.inFlightFrames)]
-        if scenedata.textures[shaderPipeline.vk].len > 0:
-          var textureCount = 0
-          for textures in scenedata.textures[shaderPipeline.vk].values:
-            textureCount += textures.len
-          poolsizes.add (VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, renderer.swapchain.inFlightFrames * textureCount * 2)
-
+        var nTextures = 0
+        for descriptor in shaderPipeline.descriptorSetLayout.descriptors:
+          if descriptor.thetype == ImageSampler:
+            nTextures += descriptor.count
+        poolsizes.add (VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nTextures * renderer.swapchain.inFlightFrames)
         scenedata.descriptorPools[shaderPipeline.vk] = renderer.device.createDescriptorSetPool(poolsizes)
 
         scenedata.descriptorSets[shaderPipeline.vk] = shaderPipeline.setupDescriptors(
--- a/semicongine/text.nim	Mon Jan 29 00:21:16 2024 +0700
+++ b/semicongine/text.nim	Wed Jan 31 00:29:40 2024 +0700
@@ -26,14 +26,15 @@
     maxLen*: int
     font*: Font
     color*: Vec4f
+    maxWidth: float32 = 0
+    # properties:
     text: seq[Rune]
-    # attributes:
     position: Vec2f
     horizontalAlignment: HorizontalAlignment = Center
     verticalAlignment: VerticalAlignment = Center
     scale: float32
     aspect_ratio: float32
-    # management:
+    # management/internal:
     dirty: bool                 # is true if any of the attributes changed
     lastRenderedText: seq[Rune] # stores the last rendered text, to prevent unnecessary updates
     mesh: Mesh
@@ -153,6 +154,29 @@
   text.text
 proc `text=`*(text: var Text, newText: seq[Rune]) =
   text.text = newText[0 ..< min(newText.len, text.maxLen)]
+
+  if text.maxWidth > 0:
+    # todo: do word wrap instead of character wrap
+    var insertNewlinesAt: seq[int]
+    var currentWidth = 0'f32
+
+    for i in 0 ..< text.text.len:
+      if text.text[i] == NEWLINE:
+        currentWidth = 0'f32
+      else:
+        currentWidth += text.font.glyphs[text.text[i]].advance
+
+        if currentWidth > text.maxWidth / text.scale and i > 0:
+          currentWidth = text.font.glyphs[text.text[i]].advance
+          insertNewlinesAt.add(i - 1)
+
+        if i < text.text.len - 1:
+          currentWidth += text.font.kerning[(text.text[i], text.text[i + 1])]
+    var n = 0
+    for newLinePos in insertNewlinesAt:
+      text.text.insert(NEWLINE, newLinePos + n)
+
+
 proc `text=`*(text: var Text, newText: string) =
   `text=`(text, newText.toRunes)
 
@@ -192,7 +216,7 @@
     text.aspect_ratio = value
     text.dirty = true
 
-proc initText*(font: Font, text = "".toRunes, maxLen: int = text.len, color = newVec4f(0.07, 0.07, 0.07, 1), scale = 1'f32, position = newVec2f(), verticalAlignment = VerticalAlignment.Center, horizontalAlignment = HorizontalAlignment.Center): Text =
+proc initText*(font: Font, text = "".toRunes, maxLen: int = text.len, color = newVec4f(0.07, 0.07, 0.07, 1), scale = 1'f32, position = newVec2f(), verticalAlignment = VerticalAlignment.Center, horizontalAlignment = HorizontalAlignment.Center, maxWidth = 0'f32): Text =
   var
     positions = newSeq[Vec3f](int(maxLen * 4))
     indices: seq[array[3, uint16]]
@@ -204,7 +228,7 @@
       [uint16(offset + 2), uint16(offset + 3), uint16(offset + 0)],
     ]
 
-  result = Text(maxLen: maxLen, text: text, font: font, dirty: true, scale: scale, position: position, aspect_ratio: 1, horizontalAlignment: horizontalAlignment, verticalAlignment: verticalAlignment)
+  result = Text(maxLen: maxLen, text: text, font: font, dirty: true, scale: scale, position: position, aspect_ratio: 1, horizontalAlignment: horizontalAlignment, verticalAlignment: verticalAlignment, maxWidth: maxWidth)
   result.mesh = newMesh(positions = positions, indices = indices, uvs = uvs, name = &"text-{instanceCounter}")
   inc instanceCounter
   result.mesh[].renameAttribute("position", POSITION_ATTRIB)
@@ -217,5 +241,5 @@
 
   result.refresh()
 
-proc initText*(font: Font, text = "", maxLen: int = text.len, color = newVec4f(0.07, 0.07, 0.07, 1), scale = 1'f32, position = newVec2f(), verticalAlignment = VerticalAlignment.Center, horizontalAlignment = HorizontalAlignment.Center): Text =
-  initText(font = font, text = text.toRunes, maxLen = maxLen, color = color, scale = scale, position = position, horizontalAlignment = horizontalAlignment, verticalAlignment = verticalAlignment)
+proc initText*(font: Font, text = "", maxLen: int = text.len, color = newVec4f(0.07, 0.07, 0.07, 1), scale = 1'f32, position = newVec2f(), verticalAlignment = VerticalAlignment.Center, horizontalAlignment = HorizontalAlignment.Center, maxWidth = 0'f32): Text =
+  initText(font = font, text = text.toRunes, maxLen = maxLen, color = color, scale = scale, position = position, horizontalAlignment = horizontalAlignment, verticalAlignment = verticalAlignment, maxWidth = maxWidth)
--- a/tests/test_font.nim	Mon Jan 29 00:21:16 2024 +0700
+++ b/tests/test_font.nim	Wed Jan 31 00:29:40 2024 +0700
@@ -12,7 +12,7 @@
   var scene = Scene(name: "main")
   # var font = loadFont("DejaVuSans.ttf", lineHeightPixels=90'f32, charset="abcdefghijklmnopqrstuvwxyz ".toRunes)
   var font = loadFont("DejaVuSans.ttf", lineHeightPixels = 210'f32)
-  var main_text = font.initText("", 32, color = newVec4f(1, 0.15, 0.15, 1), scale = 0.001)
+  var main_text = font.initText("", maxLen = 255, color = newVec4f(1, 0.15, 0.15, 1), scale = 0.0005, maxWidth = 1.0)
   var help_text = font.initText("""Controls
 
 Horizontal alignment: