changeset 525:0285ff2281b1

add: keyboard/mouse inpute test
author Sam <sam@basx.dev>
date Sat, 04 Feb 2023 02:24:41 +0700
parents 37e42b3b120d
children b72e8f562e9d
files examples/E04_input.nim
diffstat 1 files changed, 126 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/examples/E04_input.nim	Sat Feb 04 02:24:15 2023 +0700
+++ b/examples/E04_input.nim	Sat Feb 04 02:24:41 2023 +0700
@@ -1,28 +1,96 @@
+import std/tables
 import std/strutils
+import std/typetraits
 import std/times
+import std/math
 
 import semicongine
 
 type
   # define type of vertex
   VertexDataA = object
-    position: PositionAttribute[Vec2]
-    color: ColorAttribute[Vec3]
+    position: PositionAttribute[Vec3]
+    color: ColorAttribute[Vec4]
     transform: ModelTransformAttribute
   Uniforms = object
     projection: Descriptor[Mat44]
-    cursor: Descriptor[Vec2]
+
+const
+  arrow = @[
+    Vec3([-1'f32, -1'f32, 0'f32]),
+    Vec3([1'f32, -1'f32, 0'f32]),
+    Vec3([-0.3'f32, -0.3'f32, 0'f32]),
+    Vec3([-0.3'f32, -0.3'f32, 0'f32]),
+    Vec3([-1'f32, 1'f32, 0'f32]),
+    Vec3([-1'f32, -1'f32, 0'f32]),
+  ]
+  arrow_colors = @[
+    Vec4([1'f32, 0'f32, 0'f32, 1'f32]),
+    Vec4([1'f32, 0'f32, 0'f32, 1'f32]),
+    Vec4([1'f32, 0'f32, 0'f32, 1'f32]),
+    Vec4([0.8'f32, 0'f32, 0'f32, 1'f32]),
+    Vec4([0.8'f32, 0'f32, 0'f32, 1'f32]),
+    Vec4([0.8'f32, 0'f32, 0'f32, 1'f32]),
+  ]
+  # row width is 15, should sum up
+  keyrows = (
+    [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 3.0],
+    [1.2, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.8],
+    [1.8, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.2],
+    [2.1, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],
+    [3.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 3.0],
+    [1.5, 1.5, 1.5, 6, 1.5, 1.5, 1.5],
+  )
+  rowWidth = 900
+  keyHeight = 50'f32
+  keyGap = 10'f32
+  baseColor = Vec4([1'f32, 0'f32, 0'f32, 0'f32])
+  activeColor = Vec4([1'f32, 1'f32, 1'f32, 0'f32])
+  keyMap = {
+    Escape: 0, F1: 1, F2: 2, F3: 3, F4: 4, F5: 5, F6: 6, F7: 7, F8: 8, F9: 9,
+    F10: 10, F11: 11, F12: 12,
+    NumberRowExtra1: 13, `1`: 14, `2`: 15, `3`: 16, `4`: 17, `5`: 18, `6`: 19,
+    `7`: 20, `8`: 21, `9`: 22, `0`: 23, NumberRowExtra2: 24,
+    NumberRowExtra3: 25, Backspace: 26,
+    Tab: 27, Q: 28, W: 29, Key.E: 30, R: 31, T: 32, Key.Y: 33, U: 34, I: 35, O: 36,
+    P: 37, LetterRow1Extra1: 38, LetterRow1Extra2: 39, LetterRow1Extra3: 40,
+    CapsLock: 41, A: 42, S: 43, D: 44, F: 45, G: 46, H: 47, J: 48, K: 49, L: 50,
+    LetterRow2Extra1: 51, LetterRow2Extra2: 52,
+    ShiftL: 53, Key.Z: 54, Key.X: 55, C: 56, V: 57, B: 58, N: 59, M: 60,
+    LetterRow3Extra1: 61, LetterRow3Extra2: 62, LetterRow3Extra3: 63,
+    ShiftR: 64,
+    CtrlL: 65, SuperL: 66, AltL: 67, Space: 68, AltR: 69, SuperR: 70, CtrlR: 71,
+  }.toTable
 
 var
   pipeline: RenderPipeline[VertexDataA, Uniforms]
   uniforms: Uniforms
   scene: Thing
-  time: float
+  keyvertexpos: seq[Vec3]
+  keyvertexcolor: seq[Vec4]
+  keyindices: seq[array[3, uint16]]
+  rowpos = Vec2([0'f32, 0'f32])
+  i = 0'u16
+for row in keyrows.fields:
+  let
+    rowSpacePx = rowWidth - (row.len - 1) * keyGap
+    rowSpace = sum(row)
+  for key in row:
+    let keySpace = float32((key / rowSpace) * rowSpacePx)
+    keyvertexpos.add Vec3([rowpos[0], rowpos[1], 0'f32])
+    keyvertexpos.add Vec3([rowpos[0] + keySpace, rowpos[1], 0'f32])
+    keyvertexpos.add Vec3([rowpos[0] + keySpace, rowpos[1] + keyHeight, 0'f32])
+    keyvertexpos.add Vec3([rowpos[0], rowpos[1] + keyHeight, 0'f32])
+    keyvertexcolor.add [baseColor, baseColor, baseColor, baseColor]
+    keyindices.add [i, i + 1, i + 2]
+    keyindices.add [i + 2, i + 3, i]
+    rowpos[0] += keySpace + keyGap
+    i += 4
+  rowpos[0] = 0
+  rowpos[1] += keyHeight + keyGap
 
 
 proc globalUpdate(engine: var Engine, dt: float32) =
-  time += dt
-  uniforms.cursor.value = engine.input.mousePos
   uniforms.projection.value = ortho[float32](
     0'f32, float32(engine.vulkan.frameSize.x),
     0'f32, float32(engine.vulkan.frameSize.y),
@@ -30,79 +98,78 @@
   )
   engine.vulkan.device.updateUniformData(pipeline, uniforms)
 
-  let cursor = firstPartWithName[Mesh[VertexDataA]](scene, "cursor")
-  if cursor != nil:
-    for c in cursor.vertexData.color.data.mitems:
-      c[1] = (sin(time * 8) * 0.5 + 0.5) * 0.2
-      c[2] = (sin(time * 8) * 0.5 + 0.5) * 0.2
-    engine.vulkan.device.updateVertexData(cursor.vertexData.color)
-
-    var trans = translate3d(engine.input.mousePos.x, engine.input.mousePos.y, 0'f32)
-    # cursor.vertexData.transform.data = @[trans.transposed()]
-    engine.vulkan.device.updateVertexData(cursor.vertexData.transform)
-
+  let
+    mousePos = translate3d(engine.input.mousePos.x, engine.input.mousePos.y, 0'f32)
+    winsize = engine.window.size
+    center = translate3d(float32(winsize[0]) / 2'f32, float32(winsize[1]) /
+        2'f32, 0.1'f32)
+  scene.firstWithName("cursor").transform = mousePos
+  scene.firstWithName("keyboard-center").transform = center
+  var mesh = Mesh[VertexDataA, uint16](scene.firstWithName("keyboard").parts[0])
+  var hadUpdate = false
+  for key, index in keyMap.pairs:
+    if key in engine.input.keysPressed:
+      echo "Pressed ", key
+      let baseIndex = index * 4
+      mesh.vertexData.color.data[baseIndex + 0] = activeColor
+      mesh.vertexData.color.data[baseIndex + 1] = activeColor
+      mesh.vertexData.color.data[baseIndex + 2] = activeColor
+      mesh.vertexData.color.data[baseIndex + 3] = activeColor
+      hadUpdate = true
+    if key in engine.input.keysReleased:
+      echo "Released ", key
+      let baseIndex = index * 4
+      mesh.vertexData.color.data[baseIndex + 0] = baseColor
+      mesh.vertexData.color.data[baseIndex + 1] = baseColor
+      mesh.vertexData.color.data[baseIndex + 2] = baseColor
+      mesh.vertexData.color.data[baseIndex + 3] = baseColor
+      hadUpdate = true
+  if hadUpdate:
+    engine.vulkan.device.updateVertexData(mesh.vertexData.color)
 
-const
-  shape = @[
-    Vec2([ - 1'f32, - 1'f32]),
-    Vec2([1'f32, - 1'f32]),
-    Vec2([-0.3'f32, -0.3'f32]),
-    Vec2([-0.3'f32, -0.3'f32]),
-    Vec2([ - 1'f32, 1'f32]),
-    Vec2([ - 1'f32, - 1'f32]),
-  ]
-  colors = @[
-    Vec3([1'f32, 0'f32, 0'f32]),
-    Vec3([1'f32, 0'f32, 0'f32]),
-    Vec3([1'f32, 0'f32, 0'f32]),
-    Vec3([0.8'f32, 0'f32, 0'f32]),
-    Vec3([0.8'f32, 0'f32, 0'f32]),
-    Vec3([0.8'f32, 0'f32, 0'f32]),
-  ]
 
 when isMainModule:
   var myengine = igniteEngine("Input")
 
-  var cursormesh = new Mesh[VertexDataA]
+  var cursormesh = new Mesh[VertexDataA, uint16]
   cursormesh.vertexData = VertexDataA(
-    position: PositionAttribute[Vec2](data: shape, useOnDeviceMemory: true),
-    color: ColorAttribute[Vec3](data: colors),
+    position: PositionAttribute[Vec3](data: arrow, useOnDeviceMemory: true),
+    color: ColorAttribute[Vec4](data: arrow_colors),
     transform: ModelTransformAttribute(data: @[Unit44]),
   )
   # transform the cursor a bit to make it look nice
+  let cursorscale = (
+    scale2d(20'f32, 20'f32) *
+    translate2d(1'f32, 1'f32) *
+    rotate2d(-float32(PI) / 4'f32) *
+    scale2d(0.5'f32, 1'f32) *
+    rotate2d(float32(PI) / 4'f32)
+  )
   for i in 0 ..< cursormesh.vertexData.position.data.len:
-    let cursorscale = (
-      scale2d(20'f32, 20'f32) *
-      translate2d(1'f32, 1'f32) *
-      rotate2d(-float32(PI) / 4'f32) *
-      scale2d(0.5'f32, 1'f32) *
-      rotate2d(float32(PI) / 4'f32)
-    )
     let pos = Vec3([cursormesh.vertexData.position.data[i][0],
-        cursormesh.vertexData.position.data[i][1], 1'f32])
-    cursormesh.vertexData.position.data[i] = (cursorscale * pos).xy
+        cursormesh.vertexData.position.data[i][1], 0'f32])
+    cursormesh.vertexData.position.data[i] = (cursorscale * pos)
 
-  var boxmesh = new Mesh[VertexDataA]
-  boxmesh.vertexData = VertexDataA(
-    position: PositionAttribute[Vec2](data: shape),
-    color: ColorAttribute[Vec3](data: colors),
+  var keyboardmesh = new Mesh[VertexDataA, uint16]
+  keyboardmesh.indexed = true
+  keyboardmesh.vertexData = VertexDataA(
+    position: PositionAttribute[Vec3](data: keyvertexpos,
+        useOnDeviceMemory: true),
+    color: ColorAttribute[Vec4](data: keyvertexcolor),
     transform: ModelTransformAttribute(data: @[Unit44]),
   )
-  for i in 0 ..< boxmesh.vertexData.position.data.len:
-    let boxscale = translate2d(100'f32, 100'f32) * scale2d(100'f32, 100'f32)
-    let pos = Vec3([boxmesh.vertexData.position.data[i][0],
-        boxmesh.vertexData.position.data[i][1], 1'f32])
-    boxmesh.vertexData.position.data[i] = (boxscale * pos).xy
+  keyboardmesh.indices = keyindices
 
   scene = newThing("scene")
+  let keyboard = newThing("keyboard", keyboardmesh)
+  keyboard.transform = translate3d(-float32(rowWidth) / 2'f32, -float32(
+      tupleLen(keyRows) * (keyHeight + keyGap) - keyGap) / 2'f32, 0'f32)
+  scene.add newThing("keyboard-center", keyboard)
   scene.add newThing("cursor", cursormesh)
-  scene.add newThing("a box", boxmesh, newTransform(Unit44), newTransform(
-      translate3d(1'f32, 0'f32, 0'f32)))
-  scene.add newTransform(scale3d(1.5'f32, 1.5'f32, 1.5'f32))
 
   # upload data, prepare shaders, etc
   const vertexShader = generateVertexShaderCode[VertexDataA, Uniforms]("""
-    out_position = uniforms.projection * transform * vec4(position, 0, 1);
+    out_position = uniforms.projection * transform * vec4(position, 1);
   """)
   const fragmentShader = generateFragmentShaderCode[VertexDataA]()
   pipeline = setupPipeline[VertexDataA, Uniforms, uint16](