changeset 444:f9d25bc331b3

did: same for panels
author Sam <sam@basx.dev>
date Sat, 24 Feb 2024 15:35:52 +0700
parents 7629f85823a4
children 58478c5873f1
files semicongine/engine.nim semicongine/mesh.nim semicongine/panel.nim tests/test_panel.nim
diffstat 4 files changed, 53 insertions(+), 103 deletions(-) [+]
line wrap: on
line diff
--- a/semicongine/engine.nim	Sat Feb 24 14:31:15 2024 +0700
+++ b/semicongine/engine.nim	Sat Feb 24 15:35:52 2024 +0700
@@ -225,10 +225,8 @@
 func limits*(engine: Engine): VkPhysicalDeviceLimits =
   engine.gpuDevice().physicalDevice.properties.limits
 
-proc processEventsFor*(engine: Engine, panel: var Panel) =
-  panel.refresh()
-
-  let hasMouseNow = panel.contains(engine.mousePositionNormalized())
+proc processEvents*(engine: Engine, panel: var Panel) =
+  let hasMouseNow = panel.contains(engine.mousePositionNormalized, engine.getAspectRatio)
 
   # enter/leave events
   if hasMouseNow:
--- a/semicongine/mesh.nim	Sat Feb 24 14:31:15 2024 +0700
+++ b/semicongine/mesh.nim	Sat Feb 24 15:35:52 2024 +0700
@@ -133,8 +133,8 @@
   indices: openArray[array[3, uint32|uint16|uint8]],
   colors: openArray[Vec4f] = [],
   uvs: openArray[Vec2f] = [],
-  transform: Mat4 = Unit4F32,
-  instanceTransforms: openArray[Mat4] = [Unit4F32],
+  transform: Mat4 = Unit4,
+  instanceTransforms: openArray[Mat4] = [Unit4],
   material = EMPTY_MATERIAL.initMaterialData(),
   autoResize = true,
   name: string = ""
@@ -189,8 +189,8 @@
   positions: openArray[Vec3f],
   colors: openArray[Vec4f] = [],
   uvs: openArray[Vec2f] = [],
-  transform: Mat4 = Unit4F32,
-  instanceTransforms: openArray[Mat4] = [Unit4F32],
+  transform: Mat4 = Unit4,
+  instanceTransforms: openArray[Mat4] = [Unit4],
   material = EMPTY_MATERIAL.initMaterialData(),
   name: string = "",
 ): Mesh =
@@ -446,7 +446,7 @@
 proc rect*(width = 1'f32, height = 1'f32, color = "ffffffff", material = EMPTY_MATERIAL.initMaterialData()): Mesh =
   result = Mesh(
     vertexCount: 4,
-    instanceTransforms: @[Unit4F32],
+    instanceTransforms: @[Unit4],
     indexType: Small,
     smallIndices: @[[0'u16, 1'u16, 2'u16], [2'u16, 3'u16, 0'u16]],
     name: &"rect-{instanceCounter}",
@@ -467,7 +467,7 @@
 proc tri*(width = 1'f32, height = 1'f32, color = "ffffffff", material = EMPTY_MATERIAL.initMaterialData()): Mesh =
   result = Mesh(
     vertexCount: 3,
-    instanceTransforms: @[Unit4F32],
+    instanceTransforms: @[Unit4],
     name: &"tri-{instanceCounter}",
     material: material,
   )
@@ -484,7 +484,7 @@
   assert nSegments >= 3
   result = Mesh(
     vertexCount: 3 + nSegments,
-    instanceTransforms: @[Unit4F32],
+    instanceTransforms: @[Unit4],
     indexType: Small,
     name: &"circle-{instanceCounter}",
     material: material,
@@ -511,7 +511,7 @@
 
   result = Mesh(
     vertexCount: int((rows + 1) * (columns + 1)),
-    instanceTransforms: @[Unit4F32],
+    instanceTransforms: @[Unit4],
     indexType: Small,
     name: &"grid-{instanceCounter}",
     material: material,
@@ -544,7 +544,7 @@
 type
   MeshTree* = ref object
     mesh*: Mesh
-    transform*: Mat4 = Unit4F32
+    transform*: Mat4 = Unit4
     children*: seq[MeshTree]
 
 func toStringRec*(tree: MeshTree, theindent = 0): seq[string] =
@@ -567,7 +567,7 @@
       result.add current.mesh
     queue.add current.children
 
-proc updateTransforms*(tree: MeshTree, parentTransform = Unit4F32) =
+proc updateTransforms*(tree: MeshTree, parentTransform = Unit4) =
   let currentTransform = parentTransform * tree.transform
   if not tree.mesh.isNil:
     tree.mesh.transform = currentTransform
--- a/semicongine/panel.nim	Sat Feb 24 14:31:15 2024 +0700
+++ b/semicongine/panel.nim	Sat Feb 24 15:35:52 2024 +0700
@@ -30,10 +30,10 @@
       attr[uint16]("materialIndexOut", noInterpolation = true)
     ],
     outputs = [attr[Vec4f]("color")],
-    uniforms = [attr[Vec4f]("color", arrayCount = MAX_PANEL_MATERIALS)],
+    uniforms = [attr[Vec4f]("color", arrayCount = MAX_PANEL_MATERIALS), attr[float32](ASPECT_RATIO_ATTRIBUTE)],
     samplers = [attr[Texture]("panelTexture", arrayCount = MAX_PANEL_MATERIALS)],
     vertexCode = &"""
-  gl_Position = vec4({POSITION_ATTRIB}, 1.0) * {TRANSFORM_ATTRIB};
+  gl_Position = vec4({POSITION_ATTRIB}.x, {POSITION_ATTRIB}.y * Uniforms.{ASPECT_RATIO_ATTRIBUTE}, {POSITION_ATTRIB}.z, 1.0) * {TRANSFORM_ATTRIB};
   uvFrag = {UV_ATTRIB};
   materialIndexOut = {MATERIALINDEX_ATTRIBUTE};
   """,
@@ -44,14 +44,11 @@
 
 type
   Panel* = object
-    position: Vec2f
-    size: Vec2f
     texture: Texture
     horizontalAlignment: HorizontalAlignment = Center
     verticalAlignment: VerticalAlignment = Center
-    aspect_ratio: float32
     dirty: bool
-    mesh: Mesh
+    mesh*: Mesh
     # input handling
     onMouseDown*: proc(panel: var Panel, buttons: set[MouseButton])
     onMouseUp*: proc(panel: var Panel, buttons: set[MouseButton])
@@ -61,7 +58,7 @@
     hasMouse*: bool
 
 proc `$`*(panel: Panel): string =
-  &"Panel {panel.position} (size {panel.size})"
+  &"Panel {panel.mesh}"
 
 proc refresh*(panel: var Panel) =
   if not panel.dirty:
@@ -69,36 +66,23 @@
 
   var
     offsetX = case panel.horizontalAlignment
-      of Left: panel.size.x / 2
+      of Left: 0.5
       of Center: 0
-      of Right: -panel.size.x / 2
+      of Right: -0.5
     offsetY = case panel.verticalAlignment
-      of Top: panel.size.y / 2
+      of Top: 0.5
       of Center: 0
-      of Bottom: -panel.size.y / 2
+      of Bottom: -0.5
 
-  panel.mesh[POSITION_ATTRIB, 0] = newVec3f(
-    panel.position.x - panel.size.x / 2 + offsetX,
-    (panel.position.y - panel.size.y / 2 + offsetY) * panel.aspect_ratio
-  )
-  panel.mesh[POSITION_ATTRIB, 1] = newVec3f(
-    panel.position.x + panel.size.x / 2 + offsetX,
-    (panel.position.y - panel.size.y / 2 + offsetY) * panel.aspect_ratio
-  )
-  panel.mesh[POSITION_ATTRIB, 2] = newVec3f(
-    panel.position.x + panel.size.x / 2 + offsetX,
-    (panel.position.y + panel.size.y / 2 + offsetY) * panel.aspect_ratio
-  )
-  panel.mesh[POSITION_ATTRIB, 3] = newVec3f(
-    panel.position.x - panel.size.x / 2 + offsetX,
-    (panel.position.y + panel.size.y / 2 + offsetY) * panel.aspect_ratio
-  )
+  panel.mesh[POSITION_ATTRIB, 0] = newVec3f(-0.5 + offsetX, -0.5 + offsetY)
+  panel.mesh[POSITION_ATTRIB, 1] = newVec3f(+0.5 + offsetX, -0.5 + offsetY)
+  panel.mesh[POSITION_ATTRIB, 2] = newVec3f(+0.5 + offsetX, +0.5 + offsetY)
+  panel.mesh[POSITION_ATTRIB, 3] = newVec3f(-0.5 + offsetX, +0.5 + offsetY)
 
   panel.dirty = false
 
 proc initPanel*(
-  position = newVec2f(),
-  size = newVec2f(),
+  transform = Unit4,
   color = newVec4f(1, 1, 1, 1),
   texture = EMPTY_TEXTURE,
   horizontalAlignment = HorizontalAlignment.Center,
@@ -111,26 +95,26 @@
 ): Panel =
 
   result = Panel(
-    position: position,
-    size: size,
     texture: texture,
     horizontalAlignment: horizontalAlignment,
     verticalAlignment: verticalAlignment,
-    aspect_ratio: 1,
     onMouseDown: onMouseDown,
     onMouseUp: onMouseUp,
     onMouseEnter: onMouseEnter,
     onMouseMove: onMouseMove,
     onMouseLeave: onMouseLeave,
+    dirty: true,
   )
 
   result.mesh = newMesh(
+    name = &"panel-{instanceCounter}",
     positions = newSeq[Vec3f](4),
     indices = @[
       [uint16(0), uint16(1), uint16(2)],
       [uint16(2), uint16(3), uint16(0)],
     ],
-    uvs = @[newVec2f(0, 1), newVec2f(1, 1), newVec2f(1, 0), newVec2f(0, 0)], name = &"panel-{instanceCounter}"
+    uvs = @[newVec2f(0, 1), newVec2f(1, 1), newVec2f(1, 0), newVec2f(0, 0)],
+    transform = transform
   )
   result.mesh[].renameAttribute("position", POSITION_ATTRIB)
   result.mesh[].renameAttribute("uv", UV_ATTRIB)
@@ -142,32 +126,12 @@
   inc instanceCounter
   result.refresh()
 
-proc position*(panel: Panel): Vec2f =
-  panel.position
-proc `position=`*(panel: var Panel, value: Vec2f) =
-  if value != panel.position:
-    panel.position = value
-    panel.dirty = true
-
 proc color*(panel: Panel): Vec4f =
   panel.mesh.material["color", 0, Vec4f]
 proc `color=`*(panel: var Panel, value: Vec4f) =
   if value != panel.color:
     panel.mesh.material["color", 0] = value
 
-proc transform*(panel: Panel): Mat4 =
-  panel.mesh.transform
-proc `transform=`*(panel: var Panel, value: Mat4) =
-  if value != panel.transform:
-    panel.mesh.transform = value
-
-proc size*(panel: Panel): Vec2f =
-  panel.size
-proc `size=`*(panel: var Panel, value: Vec2f) =
-  if value != panel.size:
-    panel.size = value
-    panel.dirty = true
-
 proc horizontalAlignment*(panel: Panel): HorizontalAlignment =
   panel.horizontalAlignment
 proc `horizontalAlignment=`*(panel: var Panel, value: HorizontalAlignment) =
@@ -182,20 +146,13 @@
     panel.verticalAlignment = value
     panel.dirty = true
 
-proc aspect_ratio*(panel: Panel): float32 =
-  panel.aspect_ratio
-proc `aspect_ratio=`*(panel: var Panel, value: float32) =
-  if value != panel.aspect_ratio:
-    panel.aspect_ratio = value
-    panel.dirty = true
-
-proc contains*(panel: Panel, p: Vec2f): bool =
-  let cursor = panel.mesh.transform * p.toVec3
-  let p1 = panel.mesh[POSITION_ATTRIB, 0, Vec3f]
-  let p2 = panel.mesh[POSITION_ATTRIB, 2, Vec3f]
+proc contains*(panel: Panel, p: Vec2f, aspectRatio: float32): bool =
   let
+    cursor = panel.mesh.transform.inversed * p.toVec3
+    p1 = panel.mesh[POSITION_ATTRIB, 0, Vec3f]
+    p2 = panel.mesh[POSITION_ATTRIB, 2, Vec3f]
     left = min(p1.x, p2.x)
     right = max(p1.x, p2.x)
-    top = min(p1.y, p2.y)
-    bottom = max(p1.y, p2.y)
+    top = min(p1.y * aspectRatio, p2.y * aspectRatio)
+    bottom = max(p1.y * aspectRatio, p2.y * aspectRatio)
   return left <= cursor.x and cursor.x <= right and top <= cursor.y and cursor.y <= bottom
--- a/tests/test_panel.nim	Sat Feb 24 14:31:15 2024 +0700
+++ b/tests/test_panel.nim	Sat Feb 24 15:35:52 2024 +0700
@@ -12,9 +12,11 @@
     counter.dec
   counterText.text = $counter
 proc enter(panel: var Panel) =
-  panel.size = newVec2f(0.22, 0.22)
+  panel.mesh.transform = panel.mesh.transform * scale(1.05, 1.05)
+  panel.color = newVec4f(1, 0, 0, 0.3)
 proc leave(panel: var Panel) =
-  panel.size = newVec2f(0.2, 0.2)
+  panel.mesh.transform = panel.mesh.transform * scale(1 / 1.05, 1 / 1.05)
+  panel.color = newVec4f(1, 0, 0, 0.5)
 
 proc main() =
   # setup engine
@@ -29,12 +31,12 @@
     font = loadFont("DejaVuSans.ttf", lineHeightPixels = 210'f32)
     scene = Scene(name: "main")
     origin = initPanel(
-      size = newVec2f(0.005, 0.005),
+      transform = scale(0.005, 0.005),
       color = newVec4f(1, 1, 1, 1),
       texture = Texture(isGrayscale: false, colorImage: newImage[RGBAPixel](3, 3, [T, B, T, B, B, B, T, B, T]), sampler: NEAREST_SAMPLER),
     )
-    panel = initPanel(
-      size = newVec2f(0.2, 0.2),
+    button = initPanel(
+      transform = translate(0.2, 0.1) * scale(0.3, 0.1),
       color = newVec4f(1, 0, 0, 0.5),
       onMouseDown = click,
       onMouseEnter = enter,
@@ -52,46 +54,39 @@
   F6: Bottom
 Mouse:
   Left click: Increase counter
-  Right click: Decrease counter""", scale = 0.0002, position = newVec2f(-0.9, -0.9), horizontalAlignment = Left, verticalAlignment = Top)
+  Right click: Decrease counter""".toRunes, horizontalAlignment = Left, verticalAlignment = Top, transform = translate(-0.9, -0.9) * scale(0.0002, 0.0002))
 
-  counterText = font.initText($counter, maxLen = 99, scale = 0.0004)
+  counterText = font.initText(($counter).toRunes, maxLen = 99, transform = translate(0.2, 0.1) * scale(0.0004, 0.0004))
 
   scene.add counterText
-  scene.add panel
+  scene.add button
   scene.add help_text
   scene.add origin
   engine.loadScene(scene)
 
   while engine.updateInputs() == Running and not engine.keyIsDown(Escape):
-    if engine.windowWasResized():
-      var winSize = engine.getWindow().size
-      panel.aspect_ratio = winSize[0] / winSize[1]
-      counterText.aspect_ratio = winSize[0] / winSize[1]
-      origin.aspect_ratio = winSize[0] / winSize[1]
-      help_text.aspect_ratio = winSize[0] / winSize[1]
-
     if engine.keyWasPressed(F1):
-      panel.horizontalAlignment = Left
+      button.horizontalAlignment = Left
       counterText.horizontalAlignment = Left
     elif engine.keyWasPressed(F2):
-      panel.horizontalAlignment = Center
+      button.horizontalAlignment = Center
       counterText.horizontalAlignment = Center
     elif engine.keyWasPressed(F3):
-      panel.horizontalAlignment = Right
+      button.horizontalAlignment = Right
       counterText.horizontalAlignment = Right
     elif engine.keyWasPressed(F4):
-      panel.verticalAlignment = Top
+      button.verticalAlignment = Top
       counterText.verticalAlignment = Top
     elif engine.keyWasPressed(F5):
-      panel.verticalAlignment = Center
+      button.verticalAlignment = Center
       counterText.verticalAlignment = Center
     elif engine.keyWasPressed(F6):
-      panel.verticalAlignment = Bottom
+      button.verticalAlignment = Bottom
       counterText.verticalAlignment = Bottom
 
-    engine.processEventsFor(panel)
+    engine.processEvents(button)
 
-    panel.refresh()
+    button.refresh()
     counterText.refresh()
     origin.refresh()
     help_text.refresh()