Mercurial > games > semicongine
view src/semicongine/thing.nim @ 524:37e42b3b120d
fix: scene graph, input
author | Sam <sam@basx.dev> |
---|---|
date | Sat, 04 Feb 2023 02:24:15 +0700 |
parents | 311ee4e58032 |
children | e4a0450c30e3 |
line wrap: on
line source
import std/strformat import std/typetraits import ./math/matrix type Part* = ref object of RootObj thing*: Thing Thing* = ref object of RootObj name*: string transform*: Mat44 # todo: cache transform + only update VBO when transform changed parent*: Thing children*: seq[Thing] parts*: seq[Part] func `$`*(thing: Thing): string = thing.name method `$`*(part: Part): string {.base.} = &"{part.thing} -> Part" proc add*(thing: Thing, child: Thing) = child.parent = thing thing.children.add child proc add*(thing: Thing, part: Part) = part.thing = thing thing.parts.add part proc add*(thing: Thing, children: seq[Thing]) = for child in children: child.parent = thing thing.children.add child proc add*(thing: Thing, parts: seq[Part]) = for part in parts: part.thing = thing thing.parts.add part func newThing*(name: string = ""): Thing = result = new Thing result.name = name result.transform = Unit44 if result.name == "": result.name = &"Thing[{$(cast[ByteAddress](result))}]" func newThing*(name: string, firstChild: Thing, children: varargs[ Thing]): Thing = result = new Thing result.add firstChild for child in children: result.add child result.name = name result.transform = Unit44 if result.name == "": result.name = &"Thing[{$(cast[ByteAddress](result))}]" proc newThing*(name: string, firstPart: Part, parts: varargs[Part]): Thing = result = new Thing result.name = name result.add firstPart for part in parts: result.add part if result.name == "": result.name = &"Thing[{$(cast[ByteAddress](result))}]" result.transform = Unit44 func getModelTransform*(thing: Thing): Mat44 = result = Unit44 var currentThing = thing while currentThing != nil: result = currentThing.transform * result currentThing = currentThing.parent iterator allPartsOfType*[T: Part](root: Thing): T = var queue = @[root] while queue.len > 0: let thing = queue.pop for part in thing.parts: if part of T: yield T(part) for i in countdown(thing.children.len - 1, 0): queue.add thing.children[i] func firstWithName*(root: Thing, name: string): Thing = var queue = @[root] while queue.len > 0: let next = queue.pop for child in next.children: if child.name == name: return child queue.add child func firstPartWithName*[T: Part](root: Thing, name: string): T = var queue = @[root] while queue.len > 0: let next = queue.pop for child in next.children: if child.name == name: for part in child.parts: if part of T: return T(part) queue.add child func allWithName*(root: Thing, name: string): seq[Thing] = var queue = @[root] while queue.len > 0: let next = queue.pop for child in next.children: if child.name == name: result.add child queue.add child func allPartsWithName*[T: Part](root: Thing, name: string): seq[T] = var queue = @[root] while queue.len > 0: let next = queue.pop for child in next.children: if child.name == name: for part in child.parts: if part of T: result.add T(part) queue.add child iterator allThings*(root: Thing): Thing = var queue = @[root] while queue.len > 0: let next = queue.pop for child in next.children: queue.add child yield next