changeset 763:a4c757f5d17f

did: change API for ECS
author Sam <sam@basx.dev>
date Tue, 27 Jun 2023 00:17:40 +0700
parents 4f991bc3613a
children 0cd881cfe7f9
files examples/E01_hello_triangle.nim examples/E02_squares.nim examples/E03_hello_cube.nim examples/E04_input.nim examples/E10_pong.nim src/semicongine/animation.nim src/semicongine/core/matrix.nim src/semicongine/resources/mesh.nim src/semicongine/scene.nim src/semicongine/settings.nim src/semicongine/text.nim tests/test_materials.nim tests/test_mesh.nim tests/test_vulkan_wrapper.nim
diffstat 14 files changed, 52 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/examples/E01_hello_triangle.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/examples/E01_hello_triangle.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -27,10 +27,10 @@
 var
   triangle = newScene("scene", newEntity(
     "triangle",
-    newMesh(
+    {"mesh": Component(newMesh(
       [newVec3f(-0.5, 0.5), newVec3f(0, -0.5), newVec3f(0.5, 0.5)],
       [newVec4f(1, 0, 0, 1), newVec4f(0, 1, 0, 1), newVec4f(0, 0, 1, 1)],
-    )
+    ))}
   ))
   myengine = initEngine("Hello triangle")
   renderPass = myengine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode)
--- a/examples/E02_squares.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/examples/E02_squares.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -81,7 +81,7 @@
   var myengine = initEngine("Squares")
   myengine.setRenderer(myengine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode))
 
-  var scene = newScene("scene", newEntity("scene", newEntity("squares", squaremesh)))
+  var scene = newScene("scene", newEntity("scene", [], newEntity("squares", {"mesh": Component(squaremesh)})))
   myengine.addScene(scene, vertexInput, @[], transformAttribute="")
   scene.addShaderGlobal("time", 0.0'f32)
   while myengine.updateInputs() == Running and not myengine.keyWasPressed(Escape):
--- a/examples/E03_hello_cube.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/examples/E03_hello_cube.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -78,7 +78,7 @@
       main="color = outcolor;"
     )
   myengine.setRenderer(myengine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode))
-  var cube = newScene("scene", newEntity("cube", newMesh(positions=cube_pos, indices=tris, colors=cube_color)))
+  var cube = newScene("scene", newEntity("cube", {"mesh": Component(newMesh(positions=cube_pos, indices=tris, colors=cube_color))}))
   cube.addShaderGlobal("projection", Unit4f32)
   cube.addShaderGlobal("view", Unit4f32)
   cube.addShaderGlobal("model", Unit4f32)
--- a/examples/E04_input.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/examples/E04_input.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -135,15 +135,15 @@
 
   # define mesh objects
   scene = newScene("scene", newEntity("scene"))
-  scene.root.add newEntity("background", backgroundmesh)
-  let keyboard = newEntity("keyboard", keyboardmesh)
+  scene.root.add newEntity("background", {"mesh": Component(backgroundmesh)})
+  let keyboard = newEntity("keyboard", {"mesh": Component(keyboardmesh)})
   keyboard.transform = translate3d(
     -float32(rowWidth) / 2'f32,
     -float32(tupleLen(keyRows) * (keyDimension + keyGap) - keyGap) / 2'f32,
     0'f32
   )
-  scene.root.add newEntity("keyboard-center", keyboard)
-  scene.root.add newEntity("cursor", cursormesh)
+  scene.root.add newEntity("keyboard-center", [], keyboard)
+  scene.root.add newEntity("cursor", {"mesh": Component(cursormesh)})
 
   # shaders
   const
@@ -194,7 +194,7 @@
     let mousePos = translate3d(myengine.mousePosition().x + 20, myengine.mousePosition().y + 20, 0'f32)
     scene.root.firstWithName("cursor").transform = mousePos
 
-    var mesh = Mesh(scene.root.firstWithName("keyboard").components[0])
+    var mesh = Mesh(scene.root.firstWithName("keyboard")["mesh"])
     for (index, key) in enumerate(keyIndices):
       if myengine.keyWasPressed(key):
         let baseIndex = uint32(index * 4)
--- a/examples/E10_pong.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/examples/E10_pong.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -19,14 +19,14 @@
   var myengine = initEngine("Pong")
   level = newScene("scene", newEntity("Level"))
   var playerbarmesh = rect(color=barcolor)
-  var playerbar = newEntity("playerbar", playerbarmesh)
+  var playerbar = newEntity("playerbar", {"mesh": Component(playerbarmesh)})
   playerbar.transform = scale3d(barWidth, barSize, 1'f) * translate3d(0.5'f, 0'f, 0'f)
-  var player = newEntity("player", playerbar)
+  var player = newEntity("player", [], playerbar)
   player.transform = translate3d(0'f, 0.3'f, 0'f)
   level.root.add player
 
   var ballmesh = circle(color=ballcolor)
-  var ball = newEntity("ball", ballmesh)
+  var ball = newEntity("ball", {"mesh": Component(ballmesh)})
   ball.transform = scale3d(ballSize, ballSize, 1'f) * translate3d(10'f, 10'f, 0'f)
   level.root.add ball
 
--- a/src/semicongine/animation.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/src/semicongine/animation.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -4,7 +4,6 @@
 import std/strformat
 import std/algorithm
 
-import ./scene
 import ./core/matrix
 
 type
--- a/src/semicongine/core/matrix.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/src/semicongine/core/matrix.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -2,6 +2,7 @@
 import std/macros
 import std/random
 import std/strutils
+import std/strformat
 import std/typetraits
 
 import ./vector
--- a/src/semicongine/resources/mesh.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/src/semicongine/resources/mesh.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -237,7 +237,7 @@
 
   # mesh
   if node.hasKey("mesh"):
-    result.add loadMesh(root, root["meshes"][node["mesh"].getInt()], mainBuffer)
+    result[name & "_mesh"] = loadMesh(root, root["meshes"][node["mesh"].getInt()], mainBuffer)
 
 proc loadScene(root: JsonNode, scenenode: JsonNode, mainBuffer: var seq[uint8]): Scene =
   var rootEntity = newEntity("<root>")
--- a/src/semicongine/scene.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/src/semicongine/scene.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -29,7 +29,7 @@
     internal_transform: Mat4 # todo: cache transform + only update VBO when transform changed
     parent*: Entity
     children*: seq[Entity]
-    components*: seq[Component]
+    components*: Table[string, Component]
 
   EntityAnimation* = ref object of Component
     player: AnimationPlayer[Mat4]
@@ -53,7 +53,7 @@
 
 func transform*(entity: Entity): Mat4 =
   result = entity.internal_transform
-  for component in entity.components.mitems:
+  for component in entity.components.mvalues:
     if component of EntityAnimation and EntityAnimation(component).player.playing:
       result = result * EntityAnimation(component).player.currentValue
 
@@ -129,41 +129,25 @@
 proc add*(entity: Entity, child: Entity) =
   child.parent = entity
   entity.children.add child
-proc add*(entity: Entity, component: Component) =
+proc `[]=`*(entity: Entity, index: int, child: Entity) =
+  child.parent = entity
+  entity.children[index] = child
+proc `[]`*(entity: Entity, index: int): Entity =
+  entity.children[index]
+
+proc `[]=`*(entity: Entity, name: string, component: Component) =
   component.entity = entity
-  entity.components.add component
-proc add*(entity: Entity, children: seq[Entity]) =
-  for child in children:
-    child.parent = entity
-    entity.children.add child
-proc add*(entity: Entity, components: seq[Component]) =
-  for component in components:
-    component.entity = entity
-    entity.components.add component
+  entity.components[name] = component
+proc `[]`*(entity: Entity, name: string): Component =
+  entity.components[name]
 
-func newEntity*(name: string = ""): Entity =
+func newEntity*(name: string, components: openArray[(string, Component)] = [], children: varargs[Entity]): Entity =
   result = new Entity
-  result.name = name
-  result.internal_transform = Unit4
-  if result.name == "":
-    result.name = &"Entity[{$(cast[ByteAddress](result))}]"
-
-func newEntity*(name: string, firstChild: Entity, children: varargs[Entity]): Entity =
-  result = new Entity
-  result.add firstChild
   for child in children:
     result.add child
   result.name = name
-  result.internal_transform = Unit4
-  if result.name == "":
-    result.name = &"Entity[{$(cast[ByteAddress](result))}]"
-
-proc newEntity*(name: string, firstComponent: Component, components: varargs[Component]): Entity =
-  result = new Entity
-  result.name = name
-  result.add firstComponent
-  for component in components:
-    result.add component
+  for (name, comp) in components:
+    result[name] = comp
   if result.name == "":
     result.name = &"Entity[{$(cast[ByteAddress](result))}]"
   result.internal_transform = Unit4
@@ -181,7 +165,7 @@
   var queue = @[root]
   while queue.len > 0:
     let entity = queue.pop
-    for component in entity.components.mitems:
+    for component in entity.components.mvalues:
       if component of T:
         yield T(component)
     for i in countdown(entity.children.len - 1, 0):
@@ -240,8 +224,8 @@
 
 proc prettyRecursive*(entity: Entity): seq[string] =
   var compList: seq[string]
-  for comp in entity.components:
-    compList.add $comp
+  for (name, comp) in entity.components.pairs:
+    compList.add name & ": " & $comp
 
   var trans = entity.transform.col(3)
   var pos = entity.getModelTransform().col(3)
--- a/src/semicongine/settings.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/src/semicongine/settings.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -2,7 +2,6 @@
 import std/streams
 import std/parsecfg
 import std/strutils
-import std/sequtils
 import std/parseutils
 import std/strformat
 import std/tables
--- a/src/semicongine/text.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/src/semicongine/text.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -88,7 +88,7 @@
   Entity(result).transform = Unit4F32
 
   # wrap the text mesh in a new entity to preserve the font-scaling
-  var box = newEntity("box", result.mesh)
+  var box = newEntity("box", {"mesh": Component(result.mesh)})
   # box.transform = scale3d(font.fontscale * 0.002, font.fontscale * 0.002)
   box.transform = scale3d(1 / font.resolution, 1 / font.resolution)
   result.add box
--- a/tests/test_materials.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/tests/test_materials.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -4,7 +4,7 @@
 import semicongine
 
 proc main() =
-  var scene = newScene("main", root=newEntity("rect", rect()))
+  var scene = newScene("main", root=newEntity("rect", {"mesh": Component(rect())}))
   let (RT, WT, PT) = (hexToColorAlpha("A51931").asPixel, hexToColorAlpha("F4F5F8").asPixel, hexToColorAlpha("2D2A4A").asPixel)
   let
     # image from memory
--- a/tests/test_mesh.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/tests/test_mesh.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -1,8 +1,8 @@
 import semicongine
 
 proc main() =
-  var ent1 = newEntity("hoho", rect())
-  var ent2 = newEntity("hehe", ent1)
+  var ent1 = newEntity("hoho", {"mesh": Component(rect())})
+  var ent2 = newEntity("hehe", [], ent1)
   var myScene = newScene("hi", ent2)
   myScene.root.transform = translate3d(0.2'f32, 0'f32, 0'f32)
   myScene.root.children[0].transform = translate3d(0'f32, 0.2'f32, 0'f32)
--- a/tests/test_vulkan_wrapper.nim	Tue Jun 27 00:01:36 2023 +0700
+++ b/tests/test_vulkan_wrapper.nim	Tue Jun 27 00:17:40 2023 +0700
@@ -3,37 +3,37 @@
 import semicongine
 
 proc scene_different_mesh_types(): Entity =
-  result = newEntity("root",
-    newEntity("triangle1", newMesh(
+  result = newEntity("root", [],
+    newEntity("triangle1", {"mesh": Component(newMesh(
       positions=[newVec3f(0.0, -0.5), newVec3f(0.5, 0.5), newVec3f(-0.5, 0.5)],
       colors=[newVec4f(1.0, 0.0, 0.0, 1), newVec4f(0.0, 1.0, 0.0, 1), newVec4f(0.0, 0.0, 1.0, 1)],
-    )),
-    newEntity("triangle1b", newMesh(
+    ))}),
+    newEntity("triangle1b", {"mesh": Component(newMesh(
       positions=[newVec3f(0.0, -0.4), newVec3f(0.4, 0.4), newVec3f(-0.4, 0.5)],
       colors=[newVec4f(1.0, 0.0, 0.0, 1), newVec4f(0.0, 1.0, 0.0, 1), newVec4f(0.0, 0.0, 1.0, 1)],
-    )),
-    newEntity("triangle2a", newMesh(
+    ))}),
+    newEntity("triangle2a", {"mesh": Component(newMesh(
       positions=[newVec3f(0.0, 0.5), newVec3f(0.5, -0.5), newVec3f(-0.5, -0.5)],
       colors=[newVec4f(1.0, 0.0, 0.0, 1), newVec4f(0.0, 1.0, 0.0, 1), newVec4f(0.0, 0.0, 1.0, 1)],
       indices=[[0'u16, 2'u16, 1'u16]]
-    )),
-    newEntity("triangle2b", newMesh(
+    ))}),
+    newEntity("triangle2b", {"mesh": Component(newMesh(
       positions=[newVec3f(0.0, 0.4), newVec3f(0.4, -0.4), newVec3f(-0.4, -0.4)],
       colors=[newVec4f(1.0, 0.0, 0.0, 1), newVec4f(0.0, 1.0, 0.0, 1), newVec4f(0.0, 0.0, 1.0, 1)],
       indices=[[0'u16, 2'u16, 1'u16]]
-    )),
-    newEntity("triangle3a", newMesh(
+    ))}),
+    newEntity("triangle3a", {"mesh": Component(newMesh(
       positions=[newVec3f(0.4, 0.5), newVec3f(0.9, -0.3), newVec3f(0.0, -0.3)],
       colors=[newVec4f(1.0, 1.0, 0.0, 1), newVec4f(1.0, 1.0, 0.0, 1), newVec4f(1.0, 1.0, 0.0, 1)],
       indices=[[0'u32, 2'u32, 1'u32]],
       autoResize=false
-    )),
-    newEntity("triangle3b", newMesh(
+    ))}),
+    newEntity("triangle3b", {"mesh": Component(newMesh(
       positions=[newVec3f(0.4, 0.5), newVec3f(0.9, -0.3), newVec3f(0.0, -0.3)],
       colors=[newVec4f(1.0, 1.0, 0.0, 1), newVec4f(1.0, 1.0, 0.0, 1), newVec4f(1.0, 1.0, 0.0, 1)],
       indices=[[0'u32, 2'u32, 1'u32]],
       autoResize=false
-    )),
+    ))}),
   )
   for mesh in allComponentsOfType[Mesh](result):
     mesh.setInstanceData("translate", @[newVec3f()])
@@ -63,7 +63,7 @@
   mymesh2.setInstanceData("translate", @[newVec3f(0.0, 0.3)])
   mymesh3.setInstanceData("translate", @[newVec3f(-0.3, 0.0)])
   mymesh4.setInstanceData("translate", @[newVec3f(0.0, -0.3), newVec3f(0.0, 0.5)])
-  result = newEntity("root", newEntity("triangle", mymesh4, mymesh3, mymesh2, mymesh1))
+  result = newEntity("root", [], newEntity("triangle", {"mesh1": Component(mymesh4), "mesh2": Component(mymesh3), "mesh3": Component(mymesh2), "mesh4": Component(mymesh1)}))
 
 proc scene_primitives(): Entity =
   var r = rect(color="ff0000")
@@ -73,12 +73,12 @@
   r.setInstanceData("translate", @[newVec3f(0.5, -0.3)])
   t.setInstanceData("translate", @[newVec3f(0.3,  0.3)])
   c.setInstanceData("translate", @[newVec3f(-0.3,  0.1)])
-  result = newEntity("root", t, r, c)
+  result = newEntity("root", {"mesh1": Component(t), "mesh1": Component(r), "mesh1": Component(c)})
 
 proc scene_flag(): Entity =
   var r = rect(color="ff0000")
   r.updateMeshData("color", @[newVec4f(0, 0), newVec4f(1, 0), newVec4f(1, 1), newVec4f(0, 1)])
-  result = newEntity("root", r)
+  result = newEntity("root", {"mesh": Component(r)})
 
 proc main() =
   var engine = initEngine("Test")