├── examples ├── nimrod.cfg ├── sdl_engine_skeleton.nim ├── sdl_gui.nim └── sdl_skeleton.nim ├── fowltek.nimble ├── fowltek ├── assimp.nim ├── bbtree.nim ├── boundingbox.nim ├── bullet.nim ├── classlib.nim ├── clutter.nim ├── clutter │ ├── cogl.nim │ └── gtk.nim ├── either_t.nim ├── entitty.nim ├── fann.nim ├── ftgl.nim ├── genericpointer.nim ├── gl_helpers.nim ├── idgen.nim ├── importc_block.nim ├── macro_dsl.nim ├── maybe_t.nim ├── musings │ ├── README.MD │ ├── asteroids.nim │ ├── ircd.nim │ ├── ircd_hostname.nim │ └── nim3d │ │ ├── examples │ │ ├── LiberationMono-Regular.ttf │ │ ├── ak47.obj │ │ ├── beethoven.ply │ │ ├── cube.ply │ │ ├── nimrod.cfg │ │ ├── suzanne.obj │ │ ├── testapp.nim │ │ └── testmodel.nim │ │ └── lib │ │ ├── baseapp.nim │ │ ├── camera.nim │ │ ├── ftgl_manager.nim │ │ ├── models.nim │ │ ├── nodes.nim │ │ └── textnode.nim ├── neural.nim ├── parseopt_macro.nim ├── pointer_arithm.nim ├── qtree.nim ├── sdl2 │ ├── color.nim │ ├── engine.nim │ ├── engine2.nim │ ├── gui.nim │ └── spritecache.nim ├── vector_math.nim └── verlet.nim ├── readme.md └── tests └── test_bbtree.nim /examples/nimrod.cfg: -------------------------------------------------------------------------------- 1 | path = ".." 2 | -------------------------------------------------------------------------------- /examples/sdl_engine_skeleton.nim: -------------------------------------------------------------------------------- 1 | import fowltek/sdl2/engine 2 | import_all_sdl2_things 3 | 4 | var 5 | ng = newSdlEngine() 6 | running = true 7 | 8 | ng.addHandler do(E: PSdlEngine) -> bool: 9 | result = (E.evt.kind == QuitEvent) or 10 | (E.evt.kind == KeyDown and E.evt.EvKeyboard.keysym.sym == K_ESCAPE) 11 | running = not result 12 | 13 | while running: 14 | ng.handleEvents 15 | 16 | ng.setDrawColor 0,0,0,255 17 | ng.clear 18 | 19 | ng.present 20 | -------------------------------------------------------------------------------- /examples/sdl_gui.nim: -------------------------------------------------------------------------------- 1 | import fowltek/sdl2, fowltek/sdl2/gfx 2 | import fowltek/sdl2/gui, fowltek/sdl2/color 3 | import math 4 | randomize() 5 | 6 | discard SDL_Init(INIT_EVERYTHING) 7 | 8 | var 9 | window: PWindow 10 | render: PRenderer 11 | g: PGui 12 | 13 | window = CreateWindow("SDL Skeleton", 100, 100, 640,480, SDL_WINDOW_SHOWN) 14 | render = CreateRenderer(window, -1, Renderer_Accelerated or Renderer_PresentVsync or Renderer_TargetTexture) 15 | g = newGui(window) 16 | 17 | proc showMessage (s: string) = 18 | var w: PSubWindow 19 | var algn = newAlignment(South, 2) 20 | algn.add newTextArea_noInput(text = s) 21 | algn.add newButton("Okay", proc = g.delete(w)) 22 | w = newSubWindow("omg", algn) 23 | w.setPos random(640 - 100) + 100, random(480 - 80)+80 24 | g.add w 25 | 26 | w.vt.destroy = proc(W:PWidget) = 27 | let W = PSubWindow(W) 28 | echo "WINDOW FREE'D: ", W.getTitle() 29 | 30 | 31 | block: 32 | var inputArea = newTextArea() 33 | var btn1 = newButton("Herp", proc = showMessage("HERP")) 34 | btn1.setColor Blue 35 | var btn2 = newButton("GC Fullcollect", proc = GC_FullCollect()) 36 | btn2.setColor Red 37 | var algn = newAlignment(East, 8) 38 | algn.add btn1 39 | algn.add btn2 40 | var algn2 = newAlignment(South, 4) 41 | algn2.add inputArea 42 | algn2.add algn 43 | var w = newSubWindow("Input", algn2) 44 | w.setPos 100, 100 45 | g.add w 46 | 47 | var tileWindows = newButton("Tile Windows", proc = 48 | var pos = (0, 0) 49 | for widget in g.children: 50 | widget.setPos pos[0], pos[1] 51 | inc pos[1], widget.bounds.h) 52 | tileWindows.setPos 0, 480-10 53 | tileWindows.vt.pos = proc(W:PWidget; X,Y:int16) = nil 54 | g.add tileWindows 55 | 56 | var 57 | evt: TEvent 58 | runGame = true 59 | 60 | while runGame: 61 | while pollEvent(evt): 62 | if evt.kind == QuitEvent: 63 | runGame = false 64 | break 65 | g.handleEvent evt 66 | 67 | g.update() 68 | render.setDrawColor 0,0,0,255 69 | render.clear 70 | 71 | g.draw render 72 | render.present 73 | 74 | destroy render 75 | destroy window 76 | 77 | -------------------------------------------------------------------------------- /examples/sdl_skeleton.nim: -------------------------------------------------------------------------------- 1 | ## Bare-bones SDL2 example 2 | import fowltek/sdl2, fowltek/sdl2/gfx 3 | 4 | discard SDL_Init(INIT_EVERYTHING) 5 | 6 | var 7 | window: PWindow 8 | render: PRenderer 9 | 10 | window = CreateWindow("SDL Skeleton", 100, 100, 640,480, SDL_WINDOW_SHOWN) 11 | render = CreateRenderer(window, -1, Renderer_Accelerated or Renderer_PresentVsync or Renderer_TargetTexture) 12 | 13 | var 14 | evt: TEvent 15 | runGame = true 16 | fpsman: TFPSmanager 17 | fpsman.init 18 | 19 | while runGame: 20 | while pollEvent(evt): 21 | if evt.kind == QuitEvent: 22 | runGame = false 23 | break 24 | 25 | let dt = fpsman.getFramerate() / 1000 26 | 27 | render.setDrawColor 0,0,0,255 28 | render.clear 29 | 30 | render.present 31 | 32 | destroy render 33 | destroy window 34 | 35 | -------------------------------------------------------------------------------- /fowltek.nimble: -------------------------------------------------------------------------------- 1 | [Package] 2 | name = "fowltek" 3 | version = "0.9.3" 4 | author = "fowl" 5 | description = "Assorted wrappers and reusable libraries." 6 | license = "MIT" 7 | 8 | [Deps] 9 | Requires = "nim >= 0.9.3" 10 | -------------------------------------------------------------------------------- /fowltek/assimp.nim: -------------------------------------------------------------------------------- 1 | {.error: "The AssImp module has been moved to its own Babel package! Yay, progress!".} 2 | 3 | -------------------------------------------------------------------------------- /fowltek/bbtree.nim: -------------------------------------------------------------------------------- 1 | # stole from gamebox with <3 2 | # https://github.com/shawn42/gamebox 3 | import tables, fowltek/maybe_t, fowltek/boundingbox 4 | export tables, boundingbox, maybe_t 5 | 6 | type 7 | PBB_Node*[T] = ref TBB_Node[T] 8 | TBB_Node*[T] = object 9 | parent: PBB_Node[T] 10 | node_a, node_b: PBB_Node[T] 11 | bb: TBB 12 | obj: TMaybe[T] 13 | 14 | PBB_Tree*[T] = var TBB_Tree[T] 15 | TBB_Tree*[T] = object 16 | items: TTable[T, PBB_Node[T]] 17 | root: PBB_Node[T] 18 | 19 | 20 | proc newBBtree* [T] : TBB_Tree[T] = 21 | result.items = initTable[T, PBB_Node[T]](512) 22 | proc newBBnode* [T](obj: T; bb: TBB): PBB_Node[T] {. 23 | inline.} = PBB_Node[T]( 24 | obj: Just(obj), 25 | bb: bb) 26 | proc newBBnode* [T](bb: TBB): PBB_Node[T] = 27 | new result 28 | result.bb = bb 29 | 30 | proc a* [T](node: PBB_Node[T]): PBB_Node[T] {.inline.} = node.node_a 31 | proc `a=`*[T](node, val: PBB_Node[T]) {.inline.} = 32 | node.node_a = val 33 | node.node_a.parent = node 34 | proc b* [T](node: PBB_Node[T]): PBB_Node[T] {.inline.} = node.node_b 35 | proc `b=`*[T](node, val: PBB_Node[T]) {.inline.} = 36 | node.node_b = val 37 | node.node_b.parent = node 38 | 39 | proc isLeaf*[T] (node: PBB_Node[T]): bool {.inline.} = node.obj 40 | 41 | template otherchild (node, child): expr = (if node.a == child: node.b else: node.a) 42 | 43 | type E_SomeError* = object of E_Base 44 | 45 | 46 | proc updateBB* [T] (node: PBB_Node[T]) {.inline.}= 47 | if not node.isLeaf: 48 | var n = node 49 | while not n.isNil: 50 | n.bb.refitFor(n.a.bb, n.b.bb) 51 | n = n.parent 52 | 53 | 54 | proc disownChild* [T] (node, leaf: PBB_Node[T]) = 55 | if node.parent.isLeaf: 56 | raise newException(E_SomeError, "Cannot replace the child of a leaf") 57 | if not(node == node.parent.a or node == node.parent.b): 58 | raise newException(E_SomeError, "AABBNode is not a child of parent") 59 | 60 | template other: expr = otherChild(node, leaf) 61 | 62 | if node.parent.a == node: 63 | node.parent.a = other 64 | else: 65 | node.parent.b = other 66 | 67 | node.parent.updateBB 68 | 69 | proc removeSubtree*[T] (node, leaf: PBB_Node[T]): PBB_Node[T] = 70 | if leaf == node: return nil 71 | 72 | if leaf.parent == node: 73 | var oc = otherchild(node,leaf) 74 | oc.parent = node.parent 75 | return oc 76 | 77 | leaf.parent.disownChild leaf 78 | return node 79 | 80 | proc proximity* [T] (node, leaf: PBB_Node[T]): float = ( 81 | (node.bb.left + node.bb.right - leaf.bb.left - leaf.bb.right).abs + 82 | (node.bb.bottom + node.bb.top - leaf.bb.bottom - leaf.bb.top).abs) 83 | 84 | proc insertSubtree*[T] (node, leaf: PBB_Node[T]): PBB_Node[T] = 85 | if node.isLeaf: 86 | var n_n : PBB_node[T] 87 | new n_n 88 | n_n.bb = node.bb.unionFast(leaf.bb) 89 | n_n.a = node 90 | n_n.b = leaf 91 | return n_n 92 | 93 | var 94 | cost_a = node.b.bb.area + node.a.bb.unionArea(leaf.bb) 95 | cost_b = node.a.bb.area + node.b.bb.unionArea(leaf.bb) 96 | 97 | if cost_a == cost_b : 98 | cost_a = node.a.proximity(leaf) 99 | cost_b = node.b.proximity(leaf) 100 | if cost_b < cost_a: 101 | node.b = node.b.insertSubtree(leaf) 102 | else: 103 | node.a = node.a.insertSubtree(leaf) 104 | 105 | node.bb.expandToInclude leaf.bb 106 | return node 107 | 108 | proc insertLeaf*[T] (tree: PBB_Tree[T]; leaf: PBB_Node[T]) = 109 | if not tree.root.isNil: 110 | tree.root = tree.root.insertSubtree(leaf) 111 | else: 112 | tree.root = leaf 113 | 114 | proc remove*[T] (tree: PBB_Tree[T]; item: T) = 115 | if tree.items.hasKey(item): 116 | tree.root = tree.root.removeSubtree(tree.items[item]) 117 | tree.items.del item 118 | 119 | proc update*[T] (tree: PBB_Tree[T]; item: T; bb: TBB) 120 | proc insert*[T] (tree: PBB_Tree[T]; item: T; bb: TBB) = 121 | if tree.items.hasKey(item): 122 | tree.update item, bb 123 | return 124 | var leaf = newBBnode[T](item, bb) 125 | tree.items[item] = leaf 126 | tree.insertLeaf leaf 127 | 128 | proc update [T] (tree: PBB_Tree[T]; item: T; bb: TBB) = 129 | let node = tree.items[item] 130 | if node.isNil: 131 | tree.insert item, bb 132 | elif node.isLeaf: 133 | if bb notin node.bb: 134 | node.bb = bb 135 | tree.root = tree.root.removeSubtree(node) 136 | tree.insertLeaf node 137 | 138 | proc update* [T] (tree: PBB_Tree[T]; func: proc(item: T): TBB) = 139 | for key in tree.items.keys: 140 | tree.update key, func(key) 141 | 142 | proc querySubtree* [T] (node: PBB_Node[T]; bb: TBB; cb: proc(item: T)) = 143 | if node.bb.collidesWith(bb): 144 | if not node.isLeaf: 145 | node.a.querySubtree bb, cb 146 | node.b.querySubtree bb, cb 147 | else: 148 | cb node.obj.val 149 | proc query* [T] (tree: PBB_Tree[T]; bb: TBB; cb: proc(item: T)) {.inline.} = 150 | if tree.root.isNil: return 151 | tree.root.querySubtree bb, cb 152 | 153 | proc collectCollisions* [T] (tree: PBB_Tree[T]; bb: TBB; result: var seq[T]) {.inline.} = 154 | if tree.root.isNil: return 155 | let res = result.addr 156 | tree.query(bb) do (item: T): 157 | res[].add(item) 158 | 159 | proc collectCollisions* [T] (tree: PBB_Tree[T]; item: T; result: var seq[T]) {.inline.} = 160 | if tree.root.isNil: return 161 | let res = result.addr 162 | tree.query(tree.items[item].bb) do (item2: T): 163 | if item != item2: res[].add item2 164 | 165 | proc collectCollisions* [T] (tree: PBB_Tree[T]; bb: TBB|T): seq[T] {.inline.}= 166 | result = @[] 167 | tree.collectCollisions bb, result 168 | 169 | 170 | proc itemCount* [T] (tree: PBB_Tree[T]): int {.inline.} = tree.items.len 171 | 172 | ## exposed for the test, mainly 173 | proc getObj* [T] (node: PBB_Node[T]): TMaybe[T] {.inline.} = node.obj 174 | proc getBB* [T] (node: PBB_Node[T]): TBB {.inline.} = node.bb 175 | proc getRoot* [T] (tree: PBB_Tree[T]): PBB_Node[T] {.inline.} = tree.root 176 | proc hasItem* [T] (tree: PBB_Tree[T]; item: T): bool {.inline.} = tree.items.hasKey(item) 177 | 178 | when defined(usesdl2) or isMainModule: 179 | import fowltek/sdl2/engine, colors 180 | import_all_sdl2_modules 181 | import_all_sdl2_helpers 182 | 183 | let colRed = colRed.toSDLcolor 184 | 185 | proc rectangleRGBA* (R: PRenderer, BB: TBB; col: sdl2.TColor) {.inline.} = 186 | R.rectangleRGBA bb.left.int16, bb.top.int16, bb.right.int16, bb.bottom.int16, 187 | col.R, col.G, col.B, col.A 188 | 189 | proc debugDraw* [T] (some: PBB_Node[T]; R: PRenderer; depth = 0) = 190 | var col = colRed 191 | col.a = ((depth+10).min(13) * 19).uint8 192 | R.rectangleRGBA some.bb, col 193 | if not some.isLeaf: 194 | some.a.debugDraw R, depth+1 195 | some.b.debugDraw R, depth+1 196 | 197 | when compiles(debugDraw(some.bb, some.obj.val, R)): 198 | if some.isLeaf: 199 | debugDraw some.bb, some.obj.val, R 200 | 201 | proc debugDraw* [T] (some: PBB_Tree[T]; r: PRenderer) = 202 | debugDraw some.root, r 203 | 204 | 205 | when isMainModule: 206 | import unsigned 207 | 208 | import math 209 | randomize() 210 | 211 | var NG = newSdlEngine() 212 | let windowSize = NG.window.getSize 213 | 214 | var tree = newBBtree[int]() 215 | var id = 0 216 | 217 | proc debugDraw* (bb: TBB, item: int, R: PRenderer) = 218 | R.stringRGBA bb.left.int16, bb.top.int16, $item, 0,255,0,255 219 | 220 | proc insert_a_box = 221 | var box = bb(random(windowSize.x - 10) + 20, random(windowSize.y - 10) + 20, 222 | random(400)+40, random(100)+20) 223 | inc id 224 | tree.insert id, box 225 | 226 | #insert_a_box() 227 | 228 | block: 229 | template ii (i, bb): stmt = tree.insert i, bb 230 | ii 1, bb(0, 0, 10, 10) 231 | ii 2, bb(15, 0, 10, 20) 232 | ii 3, bb(0, 15, 20, 10) 233 | ii 4, bb(0, 50, 20, 5) 234 | 235 | #var bounds = tree.root.bb 236 | #var rect = rect(0, 0, 100, 100)#( bounds.width + 10).cint, (bounds.height + 10).cint) 237 | #echo rect 238 | #NG.setViewport rect.addr 239 | NG.setScale 4.0, 4.0 240 | 241 | 242 | var running = true 243 | while running: 244 | while NG.pollHandle: 245 | case NG.evt.kind 246 | of QuitEvent: 247 | running = false 248 | of MouseButtonDown: 249 | let m = evmousebutton(ng.evt) 250 | if m.button == Button_LEFT: 251 | let box = bb(m.x.int, m.y.int, 0,0) 252 | tree.query box, proc(x: int) = 253 | echo "got ", x 254 | of KeyDown: 255 | let k = evKeyboard(NG.evt).keysym.sym 256 | case k 257 | of K_SPACE: 258 | #insert_a_box() 259 | discard 260 | else:nil 261 | 262 | else:nil 263 | 264 | let dt = NG.frameDeltaFLT 265 | 266 | NG.setDrawColor 0,0,0,255 267 | NG.clear 268 | 269 | tree.debugDraw NG 270 | 271 | NG.present 272 | 273 | NG.destroy 274 | 275 | -------------------------------------------------------------------------------- /fowltek/boundingbox.nim: -------------------------------------------------------------------------------- 1 | import math 2 | type 3 | TBB* = tuple[ 4 | left, top, width, height: float] 5 | 6 | 7 | 8 | proc bb* [T: TNumber] (x, y, w, h: T): TBB {. 9 | inline.} = (x.float, y.float, w.float, h.float) 10 | proc bb* (x, y, w, h: float): TBB {. 11 | inline.} = (x,y,w,h) 12 | 13 | proc right* (a: TBB): float {.inline.} = a.left + a.width 14 | proc `right=`*(a:var TBB; x:float){.inline.}= a.width = x - a.left 15 | proc bottom*(a: TBB): float {.inline.} = a.top + a.height 16 | proc `bottom=`*(a:var TBB; y:float){.inline.} = a.height = y - a.top 17 | proc area* (a: TBB): float {.inline.} = a.width * a.height 18 | 19 | proc unionArea* (a, b: TBB): float {.inline.} = 20 | (a.right.max(b.right) - a.left.min(b.left)) * 21 | (a.bottom.max(b.bottom) - a.top.min(b.top)) 22 | 23 | proc unionFast* (a, b: TBB): TBB = 24 | result.left = a.left.min(b.left) 25 | result.top = a.top.min(b.top) 26 | result.width = a.right.max(b.right) - result.left 27 | result.height = a.bottom.max(b.bottom) - result.top 28 | 29 | proc expandToInclude* (bb: var TBB; b: TBB) = 30 | bb.left = bb.left.min(b.left) 31 | bb.top = bb.top.min(b.top) 32 | bb.width = bb.right.max(b.right) - bb.left 33 | bb.height = bb.bottom.max(b.bottom) - bb.top 34 | 35 | proc refitFor* (bb: var TBB; a, b: TBB) = 36 | reset bb 37 | bb.expandToInclude a 38 | bb.expandToInclude b 39 | 40 | proc collidesWith* (a, b: TBB): bool {.inline.} = ( 41 | ( (a.left >= b.left and a.left <= b.right) or (b.left >= a.left and b.left <= a.right) ) and 42 | ( (a.top >= b.top and a.top <= b.bottom) or (b.top >= a.top and b.top <= a.bottom) ) ) 43 | 44 | proc contains* (a, b: TBB): bool {.inline.} = 45 | ( b.left >= a.left and b.right <= a.right and 46 | b.top >= a.top and b.bottom <= a.bottom ) 47 | 48 | from fowltek/vector_math import TVector2 49 | proc contains* (a: TBB; b: TVector2[float]): bool = ( 50 | b.x >= a.left and b.x <= a.right and 51 | b.y >= a.top and b.y <= a.bottom ) 52 | 53 | -------------------------------------------------------------------------------- /fowltek/bullet.nim: -------------------------------------------------------------------------------- 1 | 2 | 3 | const 4 | LibC = "libBulletCollision.so" 5 | LibD = "libBulletDynamics.so" 6 | 7 | type 8 | ## C interface handles from Bullet-C-Api.h 9 | PPhysicsSDK = ptr TPhysicsSDK 10 | TPhysicsSDK {.pure.} = object 11 | PDynamicsWorld = ptr TDynamicsWorld 12 | TDynamicsWorld {.pure.} = object 13 | PRigidBody = ptr TRigidBody 14 | TRigidBody {.pure.} = object 15 | PCollisionShape = ptr TCollisionShape 16 | TCollisionShape {.pure.} = object 17 | PConstraint = ptr TConstraint 18 | TConstraint {.pure.} = object 19 | 20 | PCollisionBroadphase = ptr TCollisionBroadphase 21 | TCollisionBroadphase {.pure.} = object 22 | 23 | PBroadphaseProxy = ptr TBroadphaseProxy 24 | TBroadphaseProxy {.pure.} = object 25 | 26 | ## note: bullet called this `plReal`, but that name sucks 27 | when defined(BulletUseFloat): 28 | type BFloat* = cfloat 29 | else: 30 | type BFloat* = cdouble 31 | 32 | type 33 | TVector3* = tuple[x, y, z: BFloat] #array[0..2, BFloat] 34 | TQuaternion* = array[0..3, BFloat] 35 | type 36 | TBT_BroadphaseCallback* = proc(clientData, object1, object2: pointer){. 37 | cdecl.} 38 | 39 | 40 | {.push callConv: cdecl.} 41 | proc newBulletSDK*(): PPhysicsSDK {. 42 | dynlib: LibD, importc: "plNewBulletSdk".} 43 | proc destroy*(handle: PPhysicsSDK) {. 44 | dynlib: LibD, importc: "plDeletePhysicsSdk".} 45 | 46 | discard """proc createSapBroadphase*(beginCallback: TbtBroadphaseCallback; 47 | endCallback: TbtBroadphaseCallback): PCollisionBroadphase{. 48 | importc: "plCreateSapBroadphase", dynlib: LibD.} 49 | proc DestroyBroadphase*(bp: PCollisionBroadphase){. 50 | importc: "plDestroyBroadphase", dynlib: LibD.} 51 | proc CreateProxy*(bp: PCollisionBroadphase; clientData: pointer; 52 | minX, minY, minZ, maxX, maxY, maxZ: BFloat): PBroadphaseProxy{. 53 | importc: "plCreateProxy", dynlib: LibD.} 54 | proc DestroyProxy*(bp: PCollisionBroadphase; proxyHandle: PBroadphaseProxy){. 55 | importc: "plDestroyProxy", dynlib: LibD.}""" 56 | 57 | # Dynamics World 58 | proc CreateDynamicsWorld*(physicsSdk: PPhysicsSDK): PDynamicsWorld{. 59 | importc: "plCreateDynamicsWorld", dynlib: LibD.} 60 | proc destroy*(world: PDynamicsWorld){. 61 | importc: "plDeleteDynamicsWorld", dynlib: LibD.} 62 | proc StepSimulation*(world: PDynamicsWorld; timeStep: BFloat){. 63 | importc: "plStepSimulation", dynlib: LibD.} 64 | proc AddRigidBody*(world: PDynamicsWorld; obj: PRigidBody){. 65 | importc: "plAddRigidBody", dynlib: LibD.} 66 | proc RemoveRigidBody*(world: PDynamicsWorld; obj: PRigidBody){. 67 | importc: "plRemoveRigidBody", dynlib: LibD.} 68 | 69 | # Convex Meshes 70 | proc NewConvexHullShape*(): PCollisionShape{. 71 | importc: "plNewConvexHullShape", dynlib: LibD.} 72 | proc AddVertex*(convexHull: PCollisionShape; x, y, z: BFloat) {. 73 | importc: "plAddVertex", dynlib: LibD.} 74 | 75 | # Collision Shape definition 76 | proc NewSphereShape*(radius: BFloat): PCollisionShape{. 77 | importc: "plNewSphereShape", dynlib: LibD.} 78 | proc NewBoxShape*(x, y, z: BFloat): PCollisionShape{. 79 | importc: "plNewBoxShape", dynlib: LibD.} 80 | proc NewCapsuleShape*(radius, height: BFloat): PCollisionShape{. 81 | importc: "plNewCapsuleShape", dynlib: LibD.} 82 | proc NewConeShape*(radius, height: BFloat): PCollisionShape{. 83 | importc: "plNewConeShape", dynlib: LibD.} 84 | proc NewCylinderShape*(radius, height: BFloat): PCollisionShape{. 85 | importc: "plNewCylinderShape", dynlib: LibD.} 86 | proc NewCompoundShape*(): PCollisionShape{. 87 | importc: "plNewCompoundShape", dynlib: LibD.} 88 | proc AddChildShape*(shape, child: PCollisionShape; childPos: TVector3; 89 | childOrn: TQuaternion){. 90 | importc: "plAddChildShape", dynlib: LibD.} 91 | proc destroy*(shape: PCollisionShape){. 92 | importc: "plDeleteShape", dynlib: LibD.} 93 | # Rigid Body 94 | proc CreateRigidBody*(user_data: pointer; mass: cfloat; 95 | cshape: PCollisionShape): PRigidBody{. 96 | importc: "plCreateRigidBody", dynlib: LibD.} 97 | proc DeleteRigidBody*(body: PRigidBody){. 98 | importc: "plDeleteRigidBody", dynlib: LibD.} 99 | 100 | # set world transform (position/orientation) 101 | proc SetPosition*(obj: PRigidBody; position: TVector3){. 102 | importc: "plSetPosition", dynlib: LibD.} 103 | proc SetOrientation*(obj: PRigidBody; orientation: TQuaternion){. 104 | importc: "plSetOrientation", dynlib: LibD.} 105 | proc SetEuler*(yaw, pitch, roll: BFloat; orient: TQuaternion){. 106 | importc: "plSetEuler", dynlib: LibD.} 107 | proc SetOpenGLMatrix*(obj: PRigidBody; matrix: ptr BFloat){. 108 | importc: "plSetOpenGLMatrix", dynlib: LibD.} 109 | 110 | {.pop.} 111 | 112 | proc vec3(x, y, z: float): TVector3 = 113 | result.x = BFloat(x) 114 | result.y = BFloat(y) 115 | result.z = BFloat(z) 116 | 117 | when isMainModule: 118 | ## bullet/demos/..?/BulletDino.c 119 | import gl, glut, glu 120 | 121 | proc draw*() {.cdecl.} = 122 | nil 123 | 124 | let floorverts = [ 125 | [TglFLoat(-20.0), 0.0, 20.0], 126 | [TglFloat(20.0), 0.0, 20.0], 127 | [TglFloat(20.0), 0.0, -20.0], 128 | [TglFloat(-20.0), 0.0, -20.0]] 129 | var lightColor = [TglFloat(0.8), 1.0, 0.8, 1.0] 130 | 131 | var sdk = newBulletSDK() 132 | var world = sdk.createDynamicsWorld() 133 | var floorShape = newConvexHullShape() 134 | for i in 0.. <4: 135 | floorshape.addVertex(floorVerts[i][0], floorVerts[i][1], floorVerts[i][2]) 136 | var floorBody = newBoxShape(120.0, 0.0, 120.0) 137 | var floorRigidBody = createRigidBody(nil, 0.0, floorShape) 138 | var floorpos, childpos: TVector3 139 | floorRigidBody.setPosition(floorpos) 140 | 141 | world.addRigidBody floorRigidBody 142 | 143 | ## dino 144 | var dinoChildShape = newBoxShape(8.5, 8.5, 8.5) 145 | var dinoShape = newCompoundShape() 146 | var childOrn, dinoOrient: TQuaternion 147 | dinoShape.addChildShape(dinoChildShape, childpos, childorn) 148 | var dinoRigidBody = createRigidBody(nil, 1.0, dinoShape) 149 | dinoRigidBody.setPosition(vec3(-10.0, 28.0, 0.0)) 150 | seteuler(0.0, 0.0, 3.15*0.20, dinoOrient) 151 | addRigidbody(world, dinoRigidBody) 152 | 153 | glutInit() 154 | glutInitDisplayMode GLUT_RGB or GLUT_DOUBLE or GLUT_DEPTH or GLUT_STENCIL or GLUT_MULTISAMPLE 155 | 156 | echo(glutCreateWindow("Shadowy Leapin' Lizards")) 157 | 158 | glutDisplayFunc draw 159 | 160 | 161 | glEnable(constGL_CULL_FACE) 162 | glEnable GL_DEPTH_TEST 163 | glEnable GL_TEXTURE_2D 164 | glLineWidth 3.0 165 | 166 | glMatrixMode GL_PROJECTION 167 | gluPerspective 40.0, 1.0, 20.0, 100.0 168 | 169 | glMatrixMode GL_MODELVIEW 170 | gluLookat 0.0, 8.0, 6.0, 0.0, 8.0, 0.0, 0.0, 1.0, 0.0 171 | 172 | glLightmodelI GL_LIGHT_MODEL_LOCAL_VIEWER, 1 173 | glLightfv(GL_LIGHT0, GL_DIFFUSE, addr(lightcolor[0])) 174 | 175 | 176 | 177 | glutMainLoop() 178 | 179 | 180 | sdk.destroy 181 | -------------------------------------------------------------------------------- /fowltek/classlib.nim: -------------------------------------------------------------------------------- 1 | import tables, macros, strutils 2 | import fowltek/macro_dsl 3 | discard """ 4 | Copyright (c) 2012 fowlmouth 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | """ 23 | 24 | template high(a: PNimrodNode): expr = len(a)-1 25 | 26 | macro classimpl*(name, typp: expr; body: stmt): stmt {.immediate.} = 27 | ##this time I'll iterate over the body and build the object out of 28 | ##vars and procs defined 29 | result = newNimNode(nnkStmtList) 30 | 31 | var 32 | thisRecd = newNimNode(nnkRecList) 33 | typ, parent: PNimrodNode 34 | if typp.kind == nnkIdent: 35 | typ = typp 36 | elif typp.kind == nnkInfix: 37 | if typp[0].ident == !"<": 38 | ## typ < parent 39 | typ = typp[1] 40 | parent = typp[2] 41 | elif typp[0].ident == !">": 42 | ## parent > typ 43 | typ = typp[2] 44 | parent = typp[1] 45 | elif typp[0].ident == !"*" and typp[2][0].ident == !"<": ##This is exported 46 | ## typ* < parent (typ * (< parent)) 47 | ## I decided to just always export, but ill leave this here anyways 48 | typ = typp[1] 49 | parent = typp[2][1] 50 | else: 51 | quit "Invalid expression for type: "& $typp 52 | 53 | if typ.isNil: 54 | echo("typ is nil! ", treerepr(typp)) 55 | quit(1) 56 | 57 | result.add newNimNode(nnkTypeSection).add( 58 | newNimNode(nnkTypeDef).add( 59 | newNimNode(nnkPostfix).add(!!"*", typ), 60 | newEmptyNode(), 61 | newNimNode(nnkRefTy).add( 62 | newNimNode(nnkObjectTy).add( 63 | newEmptyNode(), 64 | if parent.isNil: newEmptyNode() 65 | else: newNimNode(nnkOfInherit).add(parent), 66 | thisRecd)))) 67 | 68 | var 69 | constructorName = !("new"& $name.ident) 70 | constructorImplemented = false 71 | 72 | for i in 0 .. high(body): 73 | var statement = body[i] 74 | 75 | case statement.kind 76 | of nnkVarSection: 77 | for n in 0..high(statement): 78 | thisRecd.add statement[n] 79 | of nnkProcDef, nnkMethodDef: 80 | let procname = statement.name.baseName 81 | var 82 | selfFoadd = false 83 | params = statement[3] 84 | 85 | if procname.kind == nnkIdent and procname.ident == constructorName: 86 | constructorImplemented = true 87 | selfFoadd = true 88 | 89 | if not selfFoadd and params.len > 1: 90 | ##try to find self 91 | for i in 1..params.len - 1: 92 | if params[i][0].ident == !"self": 93 | selfFoadd = true 94 | break 95 | 96 | if statement[4].kind == nnkPragma: 97 | echo "PRAGAMAMS!!" 98 | var pragmas = statement[4] 99 | var i = 0 100 | while i <= len(pragmas) - 1: 101 | echo(i) 102 | if pragmas[i].kind == nnkIdent: 103 | if pragmas[i].ident == !"constructor": 104 | constructorImplemented = true 105 | ## set self foadd to true so it wont be added to args 106 | selfFoadd = true 107 | pragmas.del i 108 | elif pragmas[i].ident == !"noself": 109 | selfFOadd = true 110 | pragmas.del i 111 | else: 112 | inc i 113 | else: 114 | inc i 115 | 116 | if not selfFoadd: ##including the return type 117 | ##inject self: type into the params 118 | insert(params, 1, 119 | newNimNode(nnkIdentDefs).add(!!"self", typ, newEmptyNode())) 120 | result.add statement 121 | 122 | of nnkCommand: 123 | if statement[0].ident == !"subclass": 124 | #change it to classimpl(name, type < this): body 125 | statement[0].ident= !"classimpl" 126 | statement[2] = newNimNode(nnkInfix).add(!!"<", statement[2], typ) 127 | 128 | result.add statement 129 | 130 | of nnkCommentStmt: 131 | result.add statement 132 | else: 133 | echo "unknown call: "& treerepr(statement) 134 | 135 | var 136 | constructor, cbody: PNimrodNode 137 | if not constructorImplemented: 138 | constructor = newProc( 139 | newNimNode(nnkPostfix).add(!!"*", !constructorName), 140 | params = [typ]) 141 | cbody = newNimNode(nnkStmtList).add(newCall("new", !!"result")) 142 | 143 | for i in 0 .. high(thisRecd): 144 | ##iterate over each field 145 | if not constructorImplemented: 146 | ##add each field to the constructor params 147 | ##in the future, handle branching types here 148 | var 149 | arg = copyNimTree(thisRecd[i]) 150 | name = if thisRecd[i][0].kind == nnkPostfix: thisRecd[i][0][1] 151 | else: thisRecd[i][0] 152 | arg[0] = name 153 | constructor[3].add arg 154 | cbody.add((!!"result").newDotExpr(name).newAssignment(name)) 155 | ##clear any default values 156 | thisRecd[i][2] = newEmptyNode() 157 | 158 | if not constructorImplemented: 159 | constructor[6] = cbody 160 | insert(result, 1, constructor) 161 | 162 | when defined(debug): 163 | echo repr(result) 164 | 165 | 166 | 167 | when isMainModule: 168 | classimpl Animal, PAnimal < TObject: 169 | var 170 | howAnnoyingItIs*: int ##exported 171 | howmuchNoiseItMakes: int ##local 172 | 173 | proc newAnimal*(): PAnimal = 174 | quit "Do not instance an animal directly" 175 | 176 | method annoy*(): string = 177 | return "generic animal says 'sup d00d'" 178 | 179 | method annoyingScore*(): int = 180 | return self.how_annoying_it_is * self.how_much_noise_it_makes 181 | 182 | subclass Cat, PCat: 183 | method annoy*(): string = return "meow" 184 | subclass Dog, PDog: 185 | method annoy*(): string = return "woof" 186 | classimpl Squirrel, PAnimal > PSquirrel: 187 | ## make sure squirrel descends from animal 188 | var 189 | foo: int 190 | method annoy*(): string = return "SQUEEEE" 191 | 192 | 193 | var c = newCat() 194 | var arr: array[0..2, PAnimal] 195 | arr[0] = newCat() 196 | arr[1] = newDog() 197 | arr[2] = newSquirrel(70) 198 | echo arr[0].annoy() 199 | echo arr[1].annoy() 200 | echo arr[2].annoy() 201 | -------------------------------------------------------------------------------- /fowltek/clutter.nim: -------------------------------------------------------------------------------- 1 | 2 | template clutterImports*(): stmt {.immediate.} = 3 | import glib2 4 | 5 | const LibName = "libclutter-1.0.so.0" 6 | 7 | clutterImports() 8 | 9 | type 10 | PActor* = ptr TActor 11 | TActor* {.pure.} = object of TGObject 12 | 13 | PStage* = ptr TStage 14 | TStage*{.pure.} = object of TActor 15 | 16 | PText* = ptr TText 17 | TText* {.pure.} = object of TActor 18 | 19 | 20 | PActorMeta* = ptr TActorMeta 21 | TActorMeta* {.pure.} = object of TGObject 22 | 23 | TAction* {.pure.} = object of TActorMeta 24 | PAction* = ptr TAction 25 | 26 | TColor* = tuple[r, g, b, a: uint8] 27 | 28 | TClutterInitError* {.size: sizeof(cint).}=enum 29 | ErrorInternal = -3, ErrorBackend = -2, ErrorThreads = -1, 30 | ErrorUnknown = 0, ErrorNone = 1 31 | converter toBool*(some: TClutterInitError): bool = some == ErrorNone 32 | 33 | discard """template CLUTTER_STAGE*(some: PActor): PStage = cast[PStage](some) 34 | """ 35 | 36 | #G_TYPE_CHECK_INSTANCE_CAST( 37 | {.push callConv: cdecl, dynlib: LibName.} 38 | 39 | proc initClutter*(argc: ptr cint; argv: ptr cstringarray): TClutterInitError {. 40 | importc: "clutter_init".} 41 | 42 | 43 | ## TODO use this: 44 | #{.push importc: "clutter_$1".} 45 | proc main*() {.importc: "clutter_main".} 46 | 47 | proc newStage*(): PActor {.importc: "clutter_stage_new".} 48 | 49 | proc stage_get_type*(): GType {.importc: "clutter_stage_get_type".} 50 | template CLUTTER_STAGE*(some: PActor): PStage = cast[PStage]( 51 | G_TYPE_CHECK_INSTANCE_CAST(some, stage_get_type())) 52 | 53 | 54 | proc text_get_type*(): GType {.importc: "clutter_text_get_type".} 55 | template CLUTTER_TEXT*(some: PActor): PText = cast[PText]( 56 | G_TYPE_CHECK_INSTANCE_CAST(some, text_get_type())) ##cast[PText](some) 57 | 58 | 59 | proc newText_priv(font_name: cstring; text: cstring): PActor {. 60 | importc: "clutter_text_new_with_text".} 61 | 62 | proc setColor*(stage: PStage; col: ptr TColor) {. 63 | importc: "clutter_stage_set_color".} 64 | 65 | proc setColor*(text: PText; col: ptr TColor) {.importc: "clutter_text_set_color".} 66 | proc getColor*(text: PText; col: ptr TColor) {.importc: "clutter_text_get_color".} 67 | 68 | proc addChild*(actor, child: PActor) {.importc: "clutter_actor_add_child".} 69 | proc show*(actor: PActor) {.importc: "clutter_actor_show".} 70 | 71 | proc newColor*(r, g, b, a: uint8): ptr TColor {.importc: "clutter_color_new".} 72 | 73 | 74 | 75 | # #define CLUTTER_TYPE_ACTION (clutter_action_get_type ()) 76 | # #define CLUTTER_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTION, ClutterAction)) 77 | # #define CLUTTER_IS_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTION)) 78 | # #define CLUTTER_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ACTION, ClutterActionClass)) 79 | # #define CLUTTER_IS_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ACTION)) 80 | # #define CLUTTER_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ACTION, ClutterActionClass)) 81 | 82 | 83 | 84 | 85 | 86 | proc action_get_type*(): GType {.importc: "clutter_action_get_type".} 87 | # ClutterActor API 88 | 89 | 90 | proc add_action*(self: PActor; action: PAction) {. 91 | importc: "clutter_actor_add_action".} 92 | proc add_action*(self: PActor; name: cstring; action: PAction) {. 93 | importc: "clutter_actor_add_action_with_name".} 94 | proc remove_action*(self: PActor; action: PAction) {.importc: "clutter_actor_remove_action".} 95 | proc remove_action*(self: PActor; name: cstring) {.importc: "clutter_actor_remove_action_by_name".} 96 | 97 | proc get_action*(self: PActor; name: cstring): PAction {. 98 | importc: "clutter_actor_get_action".} 99 | proc get_actions*(self: PActor): PGList {.importc: "clutter_actor_get_actions".} 100 | proc clear_actions*(self: PActor) {.importc: "clutter_actor_clear_actions".} 101 | proc hasActions*(self: PActor): gboolean {.importc: "clutter_actor_has_actions".} 102 | 103 | 104 | 105 | 106 | # #define CLUTTER_TYPE_ACTOR_META (clutter_actor_meta_get_type ()) 107 | # #define CLUTTER_ACTOR_META(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTOR_META, ClutterActorMeta)) 108 | # #define CLUTTER_IS_ACTOR_META(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTOR_META)) 109 | # #define CLUTTER_ACTOR_META_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ACTOR_META, ClutterActorMetaClass)) 110 | # #define CLUTTER_IS_ACTOR_META_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ACTOR_META)) 111 | # #define CLUTTER_ACTOR_META_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ACTOR_META, ClutterActorMetaClass)) 112 | 113 | proc actor_meta_get_type*(): GType {. 114 | importc: "clutter_actor_meta_get_type".} 115 | proc set_name*(meta: PActorMeta; name: cstring) {. 116 | importc: "clutter_actor_meta_set_name".} 117 | proc get_name*(meta: PActorMeta): cstring {. 118 | importc: "clutter_actor_meta_get_name".} 119 | proc set_enabled*(meta: PActorMeta; is_enabled: gboolean) {. 120 | importc: "clutter_actor_meta_set_enabled".} 121 | proc get_enabled*(meta: PActorMeta): gboolean {. 122 | importc: "clutter_actor_meta_get_enabled".} 123 | proc get_actor*(meta: PActorMeta): PActor {. 124 | importc: "clutter_actor_meta_get_actor".} 125 | 126 | 127 | 128 | 129 | {.pop.} 130 | 131 | proc newText*(font_name: cstring; text: cstring): PText = 132 | result = CLUTTER_TEXT(newText_priv(font_name, text)) 133 | -------------------------------------------------------------------------------- /fowltek/clutter/cogl.nim: -------------------------------------------------------------------------------- 1 | 2 | const LibName = "libcogl.so" 3 | 4 | type 5 | PCobject* = ptr TCobject ## 6 | TCobject* {.pure, final.} = object 7 | 8 | CoglUserDataKey* {.pure, final.} = object 9 | unused: cint 10 | 11 | CoglDebugObjectForeachTypeCallback* = proc (info: ptr CoglDebugObjectTypeInfo; 12 | user_data: pointer) 13 | CoglUserDataDestroyCallback* = proc (user_data: pointer) 14 | 15 | CoglDebugObjectTypeInfo* {.pure, final.} = object 16 | name*: cstring 17 | instance_count*: culong 18 | #* 19 | # CoglUserDataDestroyCallback: 20 | # @user_data: The data whos association with a #CoglObject has been 21 | # destoyed. 22 | # 23 | # When associating private data with a #CoglObject a callback can be 24 | # given which will be called either if the object is destroyed or if 25 | # cogl_object_set_user_data() is called with NULL user_data for the 26 | # same key. 27 | # 28 | # Since: 1.4 29 | # 30 | 31 | #define COGL_OBJECT(X) ((CoglObject *)X) 32 | template COGL_OBJECT*(x): expr = cast[PCobject](x) 33 | 34 | 35 | 36 | importcizzle "cogl_object_": 37 | proc set_user_data*(obj: PCObject; key: ptr CoglUserDataKey; 38 | user_data: pointer; destroy: CoglUserDataDestroyCallback) 39 | # Associates some private @user_data with a given #CoglObject. To 40 | # later remove the association call cogl_object_set_user_data() with 41 | # the same @key but NULL for the @user_data. 42 | proc get_user_data*(obj: PCObject; key: ptr CoglUserDataKey): pointer 43 | # Finds the user data previously associated with @object using 44 | # the given @key. If no user data has been associated with @object 45 | # for the given @key this function returns NULL. 46 | 47 | when defined(COGL_ENABLE_EXPERIMENTAL_API): 48 | proc debug_object_foreach_type*(func: CoglDebugObjectForeachTypeCallback; 49 | user_data: pointer) {.importc: "cogl_debug_object_foreach_type_EXP".} 50 | # Invokes @func once for each type of object that Cogl uses and 51 | # passes a count of the number of objects for that type. This is 52 | # intended to be used solely for debugging purposes to track down 53 | # issues with objects leaking. 54 | 55 | proc debug_object_print_instances*() {. 56 | importc: "debug_object_print_instances_EXP".} 57 | # Prints a list of all the object types that Cogl uses along with the 58 | # number of objects of that type that are currently in use. This is 59 | # intended to be used solely for debugging purposes to track down 60 | # issues with objects leaking. 61 | 62 | 63 | importcizzle "cogl_": 64 | proc rectangle*(x1, y1, x2, y2: cfloat) 65 | proc rectangle_with_texture_coords*(x1, y1, x2, y2: cfloat; tx1, ty1, tx2, ty2: cfloat) 66 | proc rectangle_with_multitexture_coords*(x1, y1, x2, y2: cfloat; tex_coords: ptr cfloat; tex_coords_len: cint) 67 | proc rectangles_with_texture_coords*(verts: ptr cfloat; n_rects: cuint) 68 | proc rectangles*(verts: ptr cfloat; n_rects: cuint) 69 | proc polygon*(vertices: ptr CoglTextureVertex; n_vertices: cuint; 70 | use_color: gboolean) 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /fowltek/clutter/gtk.nim: -------------------------------------------------------------------------------- 1 | import clutter, gtk2, glib2 2 | 3 | when defined(Linux): 4 | const libname = "libclutter-gtk-1.0.so.0" 5 | 6 | type 7 | 8 | PGtkActor* = ptr TGtkActor 9 | TGtkActor* {.pure.} = object of clutter.TActor 10 | 11 | PGtkWindow* = ptr TGtkWindow 12 | TGtkWindow* {.pure.} = object of TActor 13 | 14 | PGtkEmbed* = ptr TGtkEmbed 15 | TGtkEmbed* {.pure.} = object of TActor 16 | 17 | #GType gtk_clutter_actor_get_type (void) G_GNUC_CONST; 18 | #ClutterActor *gtk_clutter_actor_new (void); 19 | 20 | #ClutterActor *gtk_clutter_actor_new_with_contents (GtkWidget *contents); 21 | #GtkWidget * gtk_clutter_actor_get_contents (GtkClutterActor *actor); 22 | #GtkWidget * gtk_clutter_actor_get_widget (GtkClutterActor *actor); 23 | 24 | {.push: cdecl, dynlib: LibName.} 25 | 26 | proc gtk_actor_get_type*(): GType {.importc: "gtk_clutter_actor_get_type".} 27 | proc newGTKActor_c*(): PActor {.importc: "gtk_clutter_actor_new".} 28 | proc newGTKActor_c*(contents: gtk2.PWidget): PActor {. 29 | importc: "gtk_clutter_actor_new_with_contents".} 30 | 31 | proc getContents*(actor: PGtkActor): PWidget {.importc:"gtk_clutter_actor_get_contents".} 32 | proc gtkGetWidget*(actor: PGtkActor): PWidget {.importc: "gtk_clutter_actor_get_widget".} 33 | #GTK_CLUTTER_TYPE_ACTOR (gtk_clutter_actor_get_type ()) 34 | #GTK_CLUTTER_ACTOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_CLUTTER_TYPE_ACTOR, GtkClutterActor)) 35 | 36 | 37 | 38 | proc gtk_window_get_type*(): GType {.importc: "gtk_clutter_window_get_type".} 39 | proc newGTKWindow*(): PWidget {.importc: "gtk_clutter_window_new".} 40 | proc getStage*(window: PGtkWindow): PActor {.importc: "gtk_clutter_window_get_stage".} 41 | # 42 | 43 | 44 | proc gtk_embed_get_type*(): GType {.importc: "gtk_clutter_embed_get_type".} 45 | proc newGTKembed*(): PWidget {.importc: "gtk_clutter_embed_new".} 46 | proc getStage*(embed: PGtkEmbed): PActor {.importc: "gtk_clutter_embed_get_stage".} 47 | 48 | 49 | 50 | 51 | {.pop.} 52 | 53 | template GTK_CLUTTER_WINDOW*(some: PActor): expr = cast[PGtkClutterWindow]( 54 | G_TYPE_CHECK_INSTANCE_CAST(some, gtk_window_get_type())) 55 | 56 | ##define GTK_CLUTTER_TYPE_WINDOW (gtk_clutter_window_get_type ()) 57 | ##define GTK_CLUTTER_WINDOW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_CLUTTER_TYPE_WINDOW, GtkClutterWindow)) 58 | ##define GTK_CLUTTER_IS_WINDOW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_CLUTTER_TYPE_WINDOW)) 59 | ##define GTK_CLUTTER_WINDOW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_CLUTTER_TYPE_WINDOW, GtkClutterWindowClass)) 60 | ##define GTK_CLUTTER_IS_WINDOW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_CLUTTER_TYPE_WINDOW)) 61 | ##define GTK_CLUTTER_WINDOW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_CLUTTER_TYPE_WINDOW, GtkClutterWindowClass)) 62 | # 63 | 64 | 65 | template GTK_CLUTTER_ACTOR*(some: PActor): expr = cast[PGtkActor]( 66 | G_TYPE_CHECK_INSTANCE_CAST(some, gtk_actor_get_type())) 67 | 68 | proc newGTKActor*(): PGtkActor {.inline.} = GTK_CLUTTER_ACTOR(newGTKActor_c()) 69 | proc newGTKActor*(cnt: gtk2.PWidget): PGtkActor{.inline.}=GTK_CLUTTER_ACTOR(newGTKActor(cnt)) 70 | 71 | # gtk-clutter-actor.h: Gtk widget ClutterActor 72 | # 73 | # Copyright (C) 2009 Red Hat, Inc 74 | # Copyright (C) 2010 Intel Corp 75 | # 76 | # This library is free software; you can redistribute it and/or 77 | # modify it under the terms of the GNU Lesser General Public 78 | # License as published by the Free Software Foundation; either 79 | # version 2 of the License, or (at your option) any later version. 80 | # 81 | # This library is distributed in the hope that it will be useful, 82 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 83 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 84 | # Lesser General Public License for more details. 85 | # 86 | # You should have received a copy of the GNU Lesser General Public 87 | # License along with this library. If not see . 88 | # 89 | # Authors: 90 | # Alexander Larsson 91 | # Emmanuele Bassi 92 | # 93 | 94 | 95 | #G_BEGIN_DECLS 96 | # 97 | ##define 98 | ##define 99 | ##define GTK_CLUTTER_IS_ACTOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_CLUTTER_TYPE_ACTOR)) 100 | ##define GTK_CLUTTER_ACTOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_CLUTTER_TYPE_ACTOR, GtkClutterActorClass)) 101 | ##define GTK_CLUTTER_IS_ACTOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_CLUTTER_TYPE_ACTOR)) 102 | ##define GTK_CLUTTER_ACTOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_CLUTTER_TYPE_ACTOR, GtkClutterActorClass)) 103 | # 104 | 105 | discard """proc gtk_clutter_actor_get_type*(): GType 106 | proc gtk_clutter_actor_new*(): ptr ClutterActor 107 | proc gtk_clutter_actor_new_with_contents*(contents: ptr GtkWidget): ptr ClutterActor""" 108 | #G_END_DECLS 109 | 110 | 111 | # 112 | ##define GTK_CLUTTER_TYPE_EMBED (gtk_clutter_embed_get_type ()) 113 | ##define GTK_CLUTTER_EMBED(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_CLUTTER_TYPE_EMBED, GtkClutterEmbed)) 114 | ##define GTK_CLUTTER_IS_EMBED(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_CLUTTER_TYPE_EMBED)) 115 | ##define GTK_CLUTTER_EMBED_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_CLUTTER_TYPE_EMBED, GtkClutterEmbedClass)) 116 | ##define GTK_CLUTTER_IS_EMBED_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_CLUTTER_TYPE_EMBED)) 117 | ##define GTK_CLUTTER_EMBED_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_CLUTTER_TYPE_EMBED, GtkClutterEmbedClass)) 118 | # 119 | 120 | 121 | when ismainmodule: 122 | proc on_button_clicked(button: PButton; userdata: gpointer): gboolean {.cdecl.}= 123 | echo "clicked. neat huh?" 124 | return true 125 | 126 | 127 | proc local_quit(widget: pWidget, data: pgpointer){.cdecl.} = 128 | main_quit() 129 | 130 | discard initclutter(nil, nil) 131 | echo "init" 132 | var gtkwin = gtk2.window_new(gtk2.WINDOW_TOPLEVEL) 133 | var vbox = gtk2.vbox_new(false, 6) 134 | add(CONTAINER(gtkwin), vbox) 135 | show vbox 136 | 137 | var button = button_new("Change Color") 138 | pack_end(vbox, button, FALSE, FALSE, 0) 139 | show(button) 140 | 141 | discard signal_connect(`OBJECT`(button), "clicked", SIGNAL_FUNC(on_button_clicked), nil) 142 | 143 | ## /* Stop the application when the window is closed: */ 144 | discard signal_connect(`OBJECT`(gtkwin), "hide", SIGNAL_FUNC(local_quit), nil) 145 | 146 | ## /* Create the clutter widget: */ 147 | var clutter_widget = newGTKembed (); 148 | pack_start (BOX (vbox), clutter_widget, TRUE, TRUE, 0) 149 | show (clutter_widget); 150 | 151 | gtk2.main() 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /fowltek/either_t.nim: -------------------------------------------------------------------------------- 1 | 2 | type 3 | TEither* [L,R] = object 4 | case isLeft*: bool 5 | of true: left*: L 6 | of false:right*:R 7 | 8 | proc Left* (L: any; R: typedesc): auto = 9 | TEither[type(L), R](isLeft: true, left: L) 10 | proc Right*(L: typedesc, R: any): auto = 11 | TEither[L, type(R)](isLeft: false,right:R) 12 | 13 | proc isRight* [L,R] (this:TEither[L,R]): bool {.inline.} = not this.isLeft 14 | 15 | proc match* [L,R] (this:TEither[L,R]; le:proc(x:L); ri:proc(x:R)) = 16 | case this.isLeft 17 | of true: le(this.left) 18 | of false: ri(this.right) 19 | 20 | proc Either* (L:any; R:typedesc): auto = 21 | TEither[type(L),R](isLeft: true, left: L) 22 | proc Either* (L:typedesc; R:any): auto = 23 | TEither[L,type(R)](isLeft: false,right:R) 24 | 25 | when isMainModule: 26 | 27 | var y = either("Foo", int) 28 | echo y 29 | y = either(string,42) 30 | quit 0 31 | 32 | template test_match [l,r] (x: TEither[l,r]): stmt = 33 | match(x) 34 | do(msg): 35 | echo "msg: ", msg 36 | do(num): 37 | echo "num: ", num 38 | 39 | 40 | var x = Left("Foo", int) 41 | test_match x 42 | 43 | x = Right(string, 42) 44 | echo x 45 | try: 46 | echo x.left 47 | except EInvalidField: 48 | echo "EInvalidField raised on x.left (good)" 49 | test_match x 50 | 51 | -------------------------------------------------------------------------------- /fowltek/fann.nim: -------------------------------------------------------------------------------- 1 | import macros 2 | import fowltek/importc_block, fowltek/macro_dsl 3 | 4 | when defined(Linux): 5 | const 6 | LibName = "libfann.so" 7 | else: 8 | {.fatal: "Please fill out the library name for your system in fann.nim".} 9 | 10 | when defined(FannIntegers): 11 | type TFannType* = cint 12 | else: 13 | type TFannType* = cfloat 14 | 15 | type PFannType* = ptr TFannType 16 | 17 | 18 | {.pragma: dyl, dynlib: LibName.} 19 | 20 | 21 | #fann_error.h 22 | type 23 | TFannError* {.pure.} = object 24 | errno*: TFannErrorNum 25 | errorLog*: TFile 26 | errstr*: cstring 27 | PFannError* = ptr TFannError 28 | 29 | TFannErrorNum* {.size: sizeof(cint).} = enum 30 | FANN_E_NO_ERROR = 0, 31 | FANN_E_CANT_OPEN_CONFIG_R, 32 | FANN_E_CANT_OPEN_CONFIG_W, 33 | FANN_E_WRONG_CONFIG_VERSION, 34 | FANN_E_CANT_READ_CONFIG, 35 | FANN_E_CANT_READ_NEURON, 36 | FANN_E_CANT_READ_CONNECTIONS, 37 | FANN_E_WRONG_NUM_CONNECTIONS, 38 | FANN_E_CANT_OPEN_TD_W, 39 | FANN_E_CANT_OPEN_TD_R, 40 | FANN_E_CANT_READ_TD, 41 | FANN_E_CANT_ALLOCATE_MEM, 42 | FANN_E_CANT_TRAIN_ACTIVATION, 43 | FANN_E_CANT_USE_ACTIVATION, 44 | FANN_E_TRAIN_DATA_MISMATCH, 45 | FANN_E_CANT_USE_TRAIN_ALG, 46 | FANN_E_TRAIN_DATA_SUBSET, 47 | FANN_E_INDEX_OUT_OF_BOUND, 48 | FANN_E_SCALE_NOT_PRESENT 49 | 50 | 51 | {.push callConv:cdecl.} 52 | importcizzle "fann_": 53 | proc set_error_log* (errdat: PFannError, log_file: TFile) {.dyl.} 54 | proc get_errno* (errdat: PFannError): TFannErrorNum {.dyl.} 55 | proc reset_errno* (errdat: PFannError) {.dyl.} 56 | proc reset_errstr* (errdat: PFannError) {.dyl.} 57 | proc get_errstr*(errdat: PFannError): cstring {.dyl.} 58 | proc print_error*(errdat: PFannError) {.dyl.} 59 | 60 | var default_error_log* {.importc: "fann_default_error_log", dyl, noDecl.}: TFile 61 | 62 | # fann_activation.h 63 | 64 | # fann_data.h 65 | type 66 | TTrainingType* {.size:sizeof(cint).} = enum #fann_train_enum 67 | FANN_TRAIN_INCREMENTAL = 0, FANN_TRAIN_BATCH, 68 | FANN_TRAIN_RPROP, FANN_TRAIN_QUICKPROP 69 | 70 | TActivationFunc* {.size: sizeof(cint).} = enum 71 | FANN_LINEAR = 0, 72 | FANN_THRESHOLD, 73 | FANN_THRESHOLD_SYMMETRIC, 74 | FANN_SIGMOID, 75 | FANN_SIGMOID_STEPWISE, 76 | FANN_SIGMOID_SYMMETRIC, 77 | FANN_SIGMOID_SYMMETRIC_STEPWISE, 78 | FANN_GAUSSIAN, 79 | FANN_GAUSSIAN_SYMMETRIC, 80 | FANN_GAUSSIAN_STEPWISE, 81 | FANN_ELLIOT, 82 | FANN_ELLIOT_SYMMETRIC, 83 | FANN_LINEAR_PIECE, 84 | FANN_LINEAR_PIECE_SYMMETRIC, 85 | FANN_SIN_SYMMETRIC, 86 | FANN_COS_SYMMETRIC, 87 | FANN_SIN, 88 | FANN_COS 89 | 90 | TErrorFunc* {.size: sizeof(cint).} = enum 91 | FANN_ERRORFUNC_LINEAR = 0, FANN_ERRORFUNC_TANH 92 | TStopFunc* {.size: sizeof(cint).} = enum 93 | FANN_STOPFUNC_MSE = 0, FANN_STOPFUNC_BIT 94 | TNetworkType* {.size:sizeof(cint).} = enum 95 | FANN_NETTYPE_LAYER = 0, FANN_NETTYPE_SHORTCUT 96 | 97 | 98 | PFann* = ptr TFann 99 | TFann* {.pure.} = object # fann_data.h:474 100 | 101 | PTrainingData* = ptr TTrainingData 102 | TTrainingData* {.pure.} = object # fann_train.h:53 103 | errno*: TFannErrorNum 104 | errorLog*: TFile 105 | errstr*: cstring 106 | numData*, numInput*, numOutput*: cuint 107 | input*, output*: ptr PFannType 108 | 109 | TFannCallback* = proc(ann: PFann, train: PTrainingData; 110 | maxEpochs, epochsBetweenReports: cuint; desiredError: cfloat; 111 | epochs: cuint): cint {.cdecl.} 112 | 113 | PNeuron* = ptr TNeuron 114 | TNeuron* {.pure.} = object ## has #ifdef __GNUC__ __attribute__ ((packed)); 115 | firstCon*, lastCon*: cuint ## so NEEDS TESTING 116 | sum*, value*, activationSteepness*: TFannType 117 | activationFunction*: TActivationFunc 118 | 119 | TLayer* {.pure.} = object 120 | firstNeuron*: PNeuron 121 | lastNeuron*: PNeuron 122 | 123 | TConnection* {.pure.} = object 124 | fromNeuron*: cuint 125 | toNeuron*: cuint 126 | weight*: TFannType 127 | 128 | # fann_internal.h 129 | # (skipped) 130 | 131 | macro getter(nam, ty): stmt {.immediate.} = 132 | let gettername = "get_" & $nam 133 | let fann_func = "fann_" & gettername 134 | result = newProc( 135 | name = newNimNode(nnkPostfix).add(!!"*", !!gettername), 136 | params = [ 137 | ty, 138 | newNimNode(nnkIdentDefs).add(!!"ann", !!"PFann", newEmptyNode()) 139 | ] ) 140 | result.pragma = newNimNode(nnkPragma).add( 141 | !!"dyl", 142 | newNimNode(nnkExprColonExpr).add( 143 | !!"importc", newStrLitNode(fann_func) 144 | ) ) 145 | when defined(DebugGS): result.repr.echo 146 | macro setter(nam, ty): stmt {.immediate.} = 147 | let settername = "set_" & $nam 148 | let fann_func = "fann_" & settername 149 | result = newProc( 150 | name = newNimNode(nnkPostfix).add(!!"*", !!settername), 151 | params = [ 152 | !!"void", 153 | newNimNode(nnkIdentDefs).add(!!"ann", !!"PFann", newEmptyNode()), 154 | newNimNode(nnkIdentDefs).add(!!"val", ty, newEmptyNode()) 155 | ] ) 156 | result.pragma = newNimNode(nnkPragma).add( 157 | !!"dyl", 158 | newNimNode(nnkExprColonExpr).add( 159 | !!"importc", newStrLitNode(fann_func) 160 | ) ) 161 | when defined(DebugGS): result.repr.echo 162 | 163 | macro getSetter(nam, ty): stmt {.immediate.} = 164 | result = newStmtList(getAst(setter(nam, ty)), getAst(getter(nam, ty))) 165 | 166 | 167 | # fann_train.h 168 | importcizzle "fann_": 169 | proc train*(ann: PFann; input: PFannType; desiredOutput: PFannType) {.dyl.} 170 | 171 | proc test*(ann: PFann, input: PFannType; desiredOutput: PFannType): PFannType {.dyl.} 172 | 173 | proc get_MSE*(ann: PFann): cfloat {.dyl.} 174 | proc get_bit_fail*(ann: PFann): cuint {.dyl.} 175 | proc reset_MSE*(ann: PFann) {.dyl.} 176 | 177 | proc train_on_data*(ann: PFann; data: PTrainingData; maxEpochs, epochsBetweenReports: cuint; 178 | desiredError: cfloat) {.dyl.} 179 | proc train_on_file* (ann: PFann; filename: cstring; maxEpochs, epochsBetweenReports: cuint, 180 | desiredError: cfloat) {.dyl.} 181 | proc train_epoch* (ann: PFann; data: PTrainingData): cfloat {.dyl.} 182 | 183 | proc test_data* (ann: PFann; data: PTrainingData): cfloat {.dyl.} 184 | 185 | proc read_train_from_file*(ann: PFann; filename: cstring): PTrainingData {.dyl.} 186 | 187 | proc create_train_from_callback*(num_data, num_input, num_output: cuint, 188 | user_function: proc(num, num_input, num_output: cuint, 189 | input, output: PFannType): pointer {.cdecl.}): PTrainingData {.dyl.} 190 | 191 | proc destroy_train* (train_data: PTrainingData) {.dyl.} 192 | 193 | proc shuffle_train_data*(train_data: PTrainingData){.dyl.} 194 | 195 | proc scale_train*(ann: PFann; data: PTrainingData) {.dyl.} 196 | 197 | proc descale_train*(ann: PFann; data: PTrainingData){.dyl.} 198 | 199 | proc set_input_scaling_params*(ann: PFann; data: PTrainingData; 200 | newInputMin, newInputMax: cfloat): cint {.dyl.} 201 | proc set_output_scaling_params*(ann: PFann; data: PTrainingData; 202 | newOutputMin, newOutputMax: cfloat): cint {.dyl.} 203 | proc set_scaling_params*(ann: PFann; data: PTrainingData; 204 | newInputMin, newInputMax, newOutputMin, newOutputMax: cfloat): cint{.dyl.} 205 | 206 | proc clear_scaling_params*(ann: PFann): cint {.dyl.} 207 | 208 | proc scale_input* (ann: PFann; input_vector: PFannType) {.dyl.} 209 | proc scale_output* (ann: PFann; output_vector: PFannType) {.dyl.} 210 | 211 | proc descale_input*(ann: PFann; input_vector: PFannType) {.dyl.} 212 | proc descale_output*(ann: PFann; output_vector: PFannType){.dyl.} 213 | 214 | proc scale_input_train_data*(train_data: PTrainingData; newMin, newMax: TFannType){.dyl.} 215 | proc scale_output_train_data*(train_data: PTrainingData; newMin, newMax: TFannType){.dyl.} 216 | proc scale_train_data*(train_data: PTrainingData; newMin, newMax: TFannType){.dyl.} 217 | 218 | proc merge_train_data*(data1, data2: PTrainingData): PTrainingData {.dyl.} 219 | proc duplicate_train_data*(data: PTrainingData): PTrainingData {.dyl.} 220 | 221 | proc subset_train_data*(data: PTrainingData; pos, length: cuint): PTrainingData {.dyl.} 222 | 223 | proc length_train_data*(data: PTrainingData): cuint {.dyl.} 224 | proc num_input_train_data*(data: PTrainingData): cuint{.dyl.} 225 | proc num_output_train_data*(data: PTrainingData): cuint {.dyl.} 226 | proc save_train*(data: PTrainingData; filename: cstring): cint {.dyl.} 227 | proc save_train_to_fixed*(data: PTrainingData; filename: cstring; decimalPoint: cuint): cint {. 228 | dyl.} 229 | proc get_training_algorithm*(ann: PFann): TTrainingType {.dyl.} 230 | proc set_training_algorithm*(ann: PFann; algo: TTrainingType) {.dyl.} 231 | proc get_learning_rate* (ann: PFann): cfloat {.dyl.} 232 | proc set_learning_rate* (ann: PFann; rate: cfloat) {.dyl.} 233 | proc get_learning_momentum* (ann: PFann): cfloat {.dyl.} 234 | proc set_learning_momentum* (ann: PFann; momentum: cfloat) {.dyl.} 235 | 236 | 237 | proc get_activation_function*(ann: PFann; layer, neuron: cint): TActivationFunc {. 238 | dyl.} 239 | 240 | proc set_activation_function*(ann: PFann; func: TActivationFunc; layer, neuron: cint) {. 241 | dyl.} 242 | proc set_activation_function_layer*(ann: PFann; func: TActivationFunc; layer: cint) {. 243 | dyl.} 244 | proc set_activation_function_hidden* (ann: PFann, func: TActivationFunc) {. 245 | dyl.} 246 | proc set_activation_function_output* (ann: PFann, func: TActivationFunc) {. 247 | dyl.} 248 | 249 | proc get_activation_steepness* (ann: PFann; layer, neuron: cint): TFannType {. 250 | dyl.} 251 | proc set_activation_steepness* (ann: PFann; steepness: TFannType; lyaer, neuron: cint){. 252 | dyl.} 253 | 254 | proc set_activation_steepness_layer* (ann: PFann; steepness: TFannType; layer: cint){. 255 | dyl.} 256 | proc set_activation_steepness_hidden* (ann: PFann; steepness: TFannType) {.dyl.} 257 | proc set_activation_steepness_output* (ann: PFann; steepness: TFannType) {.dyl.} 258 | proc get_train_error_function*(ann: PFann): TErrorFunc {.dyl.} 259 | proc set_train_error_function*(ann: PFann; func: TErrorFunc) {.dyl.} 260 | 261 | proc get_train_stop_function*(ann: PFann): TStopFunc {.dyl.} 262 | proc set_train_stop_function*(ann: PFann; func: TStopFunc){.dyl.} 263 | proc get_bit_fail_limit*(ann: PFann): TFannType {.dyl.} 264 | proc set_bit_fail_limit*(ann: PFann; limit: TFannType) {.dyl.} 265 | 266 | proc set_callback*(ann: PFann; cb: TFannCallback) {.dyl.} 267 | proc get_quickprop_decay*(ann: PFann): cfloat {.dyl.} 268 | proc set_quickprop_decay*(ann: PFann; val: cfloat) {.dyl.} 269 | proc get_quickprop_mu*(ann: PFann): cfloat {.dyl.} 270 | proc set_quickprop_mu*(ann: PFann; val: cfloat) {.dyl.} 271 | proc get_rprop_increase_factor*(ann: PFann): cfloat{.dyl.} 272 | proc set_rprop_increase_factor*(ann: PFann; factor: cfloat){.dyl.} 273 | proc get_rprop_decrease_factor*(ann: PFann): cfloat {.dyl.} 274 | proc set_rprop_decrease_factor*(ann: PFann; val: cfloat) {.dyl.} 275 | proc get_rprop_delta_min*(ann: PFann): cfloat {.dyl.} 276 | proc set_rprop_delta_min*(ann: PFann; val: cfloat) {.dyl.} 277 | proc get_rprop_delta_max*(ann: PFann): cfloat {.dyl.} 278 | proc set_rprop_delta_max*(ann: PFann; val: cfloat) {.dyl.} 279 | proc get_rprop_delta_zero*(ann: PFann): cfloat {.dyl.} 280 | proc set_rprop_delta_zero*(ann: PFann; val: cfloat) {.dyl.} 281 | 282 | # fann_cascade.h 283 | proc cascadetrain_on_file*(ann: PFann; filename: cstring; 284 | maxNeurons, neuronsBetweenReports: cuint, desiredError: cfloat){.dyl.} 285 | proc get_cascade_output_change_fraction*(ann: PFann): cfloat {.dyl.} 286 | proc set_cascade_output_change_fraction*(ann: PFann; val: cfloat) {.dyl.} 287 | 288 | proc get_cascade_output_stagnation_epochs*(ann: PFann): cuint {.dyl.} 289 | proc set_cascade_output_stagnation_epochs*(ann: PFann; epochs: cuint) {.dyl.} 290 | proc get_cascade_candidate_change_fraction*(ann: PFann): cfloat {.dyl.} 291 | proc set_cascade_candidate_change_fraction*(ann: PFann; fraction: cfloat) {.dyl.} 292 | proc get_cascade_candidate_stagnation_epochs*(ann: PFann): cuint {.dyl.} 293 | proc set_cascade_candidate_stagnation_epochs*(ann: PFann; epochs: cuint) {.dyl.} 294 | proc get_cascade_weight_multiplier*(ann: PFann): TFannType{.dyl.} 295 | proc set_cascade_weight_multiplier*(ann: PFann; mult: TFannType) {.dyl.} 296 | 297 | getsetter cascade_candidate_limit, TFannType 298 | getsetter cascade_max_out_epochs, cuint 299 | 300 | getsetter cascade_max_cand_epochs, cuint 301 | 302 | getter cascade_num_candidates, cuint 303 | 304 | getter cascade_activation_functions_count, cuint 305 | 306 | getter cascade_activation_functions, ptr TActivationFunc 307 | 308 | 309 | proc set_cascade_activation_functions*(ann: PFann; functions: ptr TActivationFunc; 310 | functionCount: cuint) {.dyl.} 311 | 312 | proc get_cascade_activation_steepnesses_count*(ann: PFann): cuint {.dyl.} 313 | getter cascade_activation_steepnesses, PFannType 314 | 315 | proc set_cascade_activation_steepnesses*(ann: PFann; steepnesses: PFannType; count: cuint) {.dyl.} 316 | 317 | getsetter cascade_num_candidate_groups, cuint 318 | 319 | # fann_io.h 320 | proc create_from_file* (filename: cstring): PFann {.dyl.} 321 | proc save* (ann: PFann; filename: cstring): cint {.dyl.} 322 | 323 | proc save_to_fixed* (ann: PFann; filename: string): cint {.dyl.} 324 | 325 | # fann.h 326 | 327 | proc create_standard*(num_layers: cuint): PFann {.varargs, dyl.} 328 | ## arguments should be CUINT 329 | proc create_standard_array*(num_layers: cuint; layers: ptr cuint): PFann {.dyl.} 330 | 331 | proc create_sparse*(connectionRate: cfloat; numLayers: cuint): PFann {.varargs, dyl.} 332 | proc create_sparse_array*(connectionRate: cfloat; numLayers: cuint; 333 | layers: ptr cuint): PFann{.varargs, dyl.} 334 | proc create_shortcut* (numLayers: cuint): PFann {.varargs, dyl.} 335 | proc create_shortcut_array* (numLayers: cuint; layers: ptr cuint): PFann {.dyl.} 336 | proc destroy* (ann: PFann) {.dyl.} 337 | 338 | proc run* (ann: PFann; input: PFannType): PFannType {.dyl.} 339 | proc randomize_weights*(ann: PFann; minWeight, maxWeight: TFannType) {.dyl.} 340 | 341 | proc init_weights*(ann: PFann; trainingData: PTrainingData) {.dyl.} 342 | 343 | proc print_connections*(ann: PFann) {.dyl.} 344 | proc print_parameters*(ann: PFann) {.dyl.} 345 | 346 | getter num_input, cuint 347 | getter num_output, cuint 348 | getter total_neurons, cuint 349 | getter total_connections, cuint 350 | getter network_type, TNetworkType 351 | getter connection_rate, cfloat 352 | getter num_layers, cuint 353 | proc get_layer_array*(ann: PFann; layers: ptr cuint) {.dyl.} 354 | proc get_bias_array*(ann: PFann; bias: ptr cuint) {.dyl.} 355 | proc get_connection_array*(ann: PFann; connections: ptr TConnection) {.dyl.} 356 | proc set_weight_array*(ann: PFann; connections: ptr TConnection; numConnections: cuint) {.dyl.} 357 | proc set_weight*(ann: PFann; fromNeuron, toNeuron: cuint; weight: TFannType){.dyl.} 358 | getsetter user_data, pointer 359 | 360 | when defined(FannIntegers): 361 | getter decimal_point, cuint 362 | getter multiplier, cuint 363 | 364 | {.pop.} 365 | 366 | 367 | 368 | # Nimrod helpers 369 | 370 | proc destroy* (some: PTrainingData) {.inline.} = destroy_train(some) 371 | 372 | proc len* (some: PTrainingData): int {.inline.} = some.length_train_data.int 373 | 374 | 375 | -------------------------------------------------------------------------------- /fowltek/ftgl.nim: -------------------------------------------------------------------------------- 1 | 2 | when defined(Linux): 3 | const LibName = "libftgl.so.2.1.3" 4 | 5 | type 6 | TRenderMode* = enum 7 | RenderFront = 0x0001, RenderBack = 0x0002, 8 | RenderSide = 0x0004, RenderAll = 0xffff 9 | 10 | TTextAlignment* = enum 11 | AlignLeft, AlignCenter, AlignRight, AlignJustify 12 | 13 | PFont* = ptr TFont 14 | TFont* {.pure.}= object 15 | 16 | PLayout* = ptr TLayout 17 | TLayout* {.pure.} = object 18 | 19 | Bool32* {.size: sizeof(cint).} = enum 20 | False32, True32 21 | 22 | converter toBool*(a: Bool32): bool = bool(a) 23 | 24 | {.push: cdecl.} 25 | proc destroy*(font: PFont) {. 26 | importc: "ftglDestroyFont", dynlib: LibName.} 27 | 28 | proc createPixmapFont*(filename: cstring): PFont {. 29 | importc: "ftglCreatePixmapFont", dynlib: LibName.} 30 | proc createBitmapFont*(filename: cstring): PFont {. 31 | importc: "ftglCreateBitmapFont", dynlib: LibName.} 32 | proc createPolygonFont*(filename: cstring): PFont {. 33 | importc: "ftglCreatePolygonFont", dynlib: LibName.} 34 | proc createExtrudeFont*(filename: cstring): PFont {. 35 | importc: "ftglCreateExtrudeFont", dynlib: LibName.} 36 | proc createOutlineFont*(filename: cstring): PFont {. 37 | importc: "ftglCreateOutlineFont", dynlib: LibName.} 38 | proc createTextureFont*(filename: cstring): PFont {. 39 | importc: "ftglCreateTextureFont", dynlib: LibName.} 40 | 41 | proc setFaceSize*(font: PFont; size, res: cuint): bool32 {. 42 | importc: "ftglSetFontFaceSize", dynlib: LibName.} 43 | 44 | proc getFaceSize*(font: PFont): cuint {. 45 | importc: "ftglGetFontFaceSize", dynlib: LibName.} 46 | 47 | 48 | proc render*(font: PFont; text: cstring; mode: cint) {. 49 | importc: "ftglRenderFont", dynlib: LibName.} 50 | proc render*(font: PFont; text: cstring; mode: TRenderMode) {. 51 | importc: "ftglRenderFont", dynlib: LibName.} 52 | 53 | proc destroy*(layout: PLayout) {.importc: "ftglDestroyLayout", dynlib: LibName.} 54 | proc getBBox*(layout: PLayout; text: cstring; bounds: var array[0..5, cfloat]) {. 55 | importc: "ftglGetLayoutBBox", dynlib: LibName.} 56 | 57 | proc render*(layout: PLayout; text: cstring; mode: cint) {. 58 | importc: "ftglRenderLayout", dynlib: LibName.} 59 | proc render*(layout: PLayout; text: cstring; mode: TRenderMode) {. 60 | importc: "ftglRenderLayout", dynlib: LibName.} 61 | 62 | proc createSimpleLayout*(): PLayout {. 63 | importc: "ftglCreateSimpleLayout", dynlib: LibName.} 64 | 65 | proc setFont*(layout: PLayout; font: PFont) {. 66 | importc: "ftglSetLayoutFont", dynlib: LibName.} 67 | proc getFont(layout: PLayout): PFont {. 68 | importc: "ftglGetLayoutFont", dynlib: LibName.} 69 | 70 | proc setLineLength*(layout: PLayout; len: cfloat) {. 71 | importc: "ftglSetLayoutLineLength", dynlib: LibName.} 72 | proc getLineLength*(layout: PLayout): cfloat {. 73 | importc: "ftglGetLayoutLineLength", dynlib: LibName.} 74 | 75 | proc setAlignment*(layout: PLayout; alignment: cint) {. 76 | importc: "ftglSetLayoutAlignment", dynlib: LibName.} 77 | proc getAlignment*(layout: PLayout): cint {. 78 | importc: "ftglGetLayoutAlignement", dynlib: LibName.} 79 | 80 | proc setLineSpacing*(layout: PLayout; spacing: cfloat) {. 81 | importc: "ftglSetLayoutLineSpacing", dynlib: LibName.} 82 | when false: 83 | ## this is in the header but not exported.. 84 | proc getLineSpacing*(layout: PLayout): cfloat {. 85 | importc: "ftglGetLayoutLineSpacing", dynlib: LibName.} 86 | 87 | {.pop.} 88 | 89 | ## See these newlines and 90 | ## look towards the future! 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /fowltek/genericpointer.nim: -------------------------------------------------------------------------------- 1 | import macros, strutils 2 | discard """ 3 | Copyright (c) 2012 fowlmouth 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | Lulz be with you. 23 | """" 24 | 25 | ## When the hell would I use this? 26 | ## 27 | ## Imagine you are interfacing with a c function which takes a 28 | ## generic pointer (Pointer) one of the first things you're going 29 | ## to do is cast it to the type you're expecting, this just takes 30 | ## that step out for you, adds a 31 | ## `var argName = cast[desiredType](arg0)` 32 | ## to the proc body for each genericpointer[] arg declared 33 | 34 | macro genericpointer*(someProc: expr): stmt = 35 | assert someProc.kind == nnkProcDef 36 | var 37 | params = someProc[3] 38 | body = someProc[6] 39 | genericArgs = 0 40 | overloadedParams = newNimNode(nnkVarSection) 41 | for i in 1..len(params)-1: 42 | var 43 | p = params[i] 44 | name = p[0] 45 | ty = p[1] 46 | 47 | if ty.kind == nnkBracketExpr and ($ty[0].ident).tolower == "genericpointer": 48 | ## this is a genericparam[sometype] 49 | var 50 | ptype = ty[1] 51 | newParams = newNimNode(nnkIdentDefs) 52 | cst = newNimNode(nnkCast) 53 | fakename = newIdentNode("arg" & $genericArgs) 54 | cst.add ptype, fakename 55 | newParams.add name, ptype, cst 56 | overloadedParams.add newParams 57 | ## rename the parameter to ArgX and change it to a pointer 58 | p[0] = fakename 59 | p[1] = newIdentNode("pointer") 60 | inc genericArgs 61 | 62 | if overloadedParams.len > 0: 63 | body.add(body[len(body)-1]) 64 | for i in countdown(len(body)-2, 0): 65 | echo i 66 | body[i + 1] = body[i] 67 | body[0] = overloadedParams 68 | 69 | when defined(Debug): 70 | echo repr(someProc) 71 | 72 | return someProc 73 | 74 | 75 | when isMainModule: 76 | proc doo(y: genericpointer[ptr int]): int {.genericpointer, cdecl.} = 77 | echo "y is ", y[] 78 | return y[] * 2 79 | 80 | var i = 50 81 | assert doo(addr i) == i * 2 82 | var ii = cast[ptr int](alloc(sizeof(int))) 83 | ii[] = 5000 84 | assert doo(ii) == 10_000 85 | assert doo(cast[pointer](ii)) == 10_000 -------------------------------------------------------------------------------- /fowltek/gl_helpers.nim: -------------------------------------------------------------------------------- 1 | import opengl, math, vector_math 2 | type 3 | TVector2f* = TVector2[GLfloat] 4 | TVector2i* = TVector2[GLint] 5 | TVector3f* = TVector3[GLfloat] 6 | TColor4b* = TVector4[GLubyte] 7 | TColor3b* = TVector3[GLubyte] 8 | TColor4f* = TVector4[GLclampf] 9 | TColor3f* = TVector3[GLclampf] 10 | TVector2u* = TVector2[GLuint] 11 | let 12 | Vec2fZero* = vec2[GLfloat](0, 0) 13 | Vec3fZero* = vec3[GLfloat](0, 0, 0) 14 | var quadObj: PGluQuadric 15 | 16 | proc init*() = 17 | ## call after setting up a context and after opengl.loadExtensions() 18 | if not isNil(quadObj): 19 | gluDeleteQuadric(quadObj) 20 | quadObj = gluNewQuadric() 21 | 22 | proc radians*(deg: float): float = deg * PI / 180.0 23 | proc degrees*(rad: float): float = rad * 180.0 / PI 24 | 25 | proc vec2f*[A](x, y: A): TVector2f = 26 | result.x = GLfloat(x) 27 | result.y = GLfloat(y) 28 | proc vec3f*[A](x, y, z: A): TVector3f = 29 | result.x = GLfloat(x) 30 | result.y = GLfloat(y) 31 | result.z = GLfloat(z) 32 | 33 | proc color*(r, g, b: float; a = 1.0):TColor4b = vec4[GLubyte]( 34 | (r * 255.0).glubyte, (g * 255.0).glubyte, 35 | (b * 255.0).glubyte, (a * 255.0).glubyte) 36 | proc color*(r, g, b: GLubyte; a = GLubyte(255)): TColor4b = 37 | result.x = r 38 | result.y = g 39 | result.z = b 40 | result.w = a 41 | proc color*(r, g, b: int; a = 255): TColor4b = 42 | return color(GLubyte(r), GLubyte(g), GLubyte(b), GLubyte(a)) 43 | 44 | proc colorf*(r, g, b: float; a = 1.0): TColor4f = vec4[GLclampf]( 45 | r, g, b, a) 46 | proc colorf*(r, g, b: range[0..255]; 47 | a: range[0..255] = 255): TColor4f = vec4[GLclampf]( 48 | r / 255, g / 255, b / 255, a / 255) 49 | 50 | template beginGL*(kind: GLenum, body: stmt): stmt = 51 | glBegin(kind) 52 | body 53 | glEnd() 54 | 55 | template pushMatrixGL*(body: stmt): stmt = 56 | glPushMatrix() 57 | body 58 | glPopMatrix() 59 | 60 | proc glColorFV*(a: var TColor4f) {.inline.} = glColor4FV(addr a.x) 61 | proc glColorFV*(a: var TColor3f) {.inline.} = glColor3fv(addr a.x) 62 | proc glColorFV*(a: var TColor4b) {.inline.} = glColor4ubv(addr a.x) 63 | proc glColorFV*(a: var TColor3b) {.inline.} = glColor3ubv(addr a.x) 64 | 65 | proc glColor*(c: TColor4f) {.inline.} = glColor4f(c.x, c.y, c.z, c.w) 66 | proc glColor*(c: TColor4b) {.inline.} = glColor4ub(c.x, c.y, c.z, c.w) 67 | proc glColor*(c: TColor3f) {.inline.} = glColor3f(c.x, c.y, c.z) 68 | proc glColor*(c: TColor3b) {.inline.} = glColor3ub(c.x, c.y, c.z) 69 | 70 | proc glClearColor*(c: TColor4f) {.inline.} = glClearColor(c.x, c.y, c.z, c.w) 71 | 72 | proc glVertexFV*(a: var TVector3f) {.inline.}= 73 | glVertex3fv(addr a.x) 74 | proc glVertexFV*(a: var TVector2f) {.inline.}= 75 | glVertex2fv(addr a.x) 76 | 77 | proc randF*(prec = 10_000): float = random(prec)/prec 78 | proc random*[T](s: TSlice[T]): T = T(randf() * float(s.b - s.a)) + s.a 79 | 80 | 81 | proc drawBox*(size: GLfloat, kind: GLenum) = 82 | const 83 | n = [ vec3f(-1, 0, 0), 84 | vec3f( 0, 1, 0), 85 | vec3f( 1, 0, 0), 86 | vec3f( 0,-1, 0), 87 | vec3f( 0, 0, 1), 88 | vec3f( 0, 0,-1) ] 89 | faces = [ 90 | [0, 1, 2, 3], 91 | [3, 2, 6, 7], 92 | [7, 6, 5, 4], 93 | [4, 5, 1, 0], 94 | [5, 6, 2, 1], 95 | [7, 4, 0, 3]] 96 | let 97 | sz: GLfloat = -size / 2.0 98 | var 99 | v = [ 100 | vec3f(-sz, -sz, -sz), 101 | vec3f(-sz, -sz, sz), 102 | vec3f(-sz, sz, sz), 103 | vec3f(-sz, sz, -sz), 104 | vec3f( sz, -sz, -sz), 105 | vec3f( sz, -sz, sz), 106 | vec3f( sz, sz, sz), 107 | vec3f( sz, sz, -sz) ] 108 | 109 | for i in countdown(5, 0): 110 | beginGL(kind): 111 | glNormal3f(n[i].x, n[i].y, n[i].z) 112 | glVertex3fv(addr v[faces[i][0]].x) 113 | glVertex3fv(addr v[faces[i][1]].x) 114 | glVertex3fv(addr v[faces[i][2]].x) 115 | glVertex3fv(addr v[faces[i][3]].x) 116 | 117 | 118 | proc drawWireCube*(size: GLfloat) {.inline.} = 119 | drawBox(size, GL_LINE_LOOP) 120 | 121 | proc drawSolidCube*(size: GLfloat) {.inline.} = 122 | drawBox(size, GL_QUADS) 123 | 124 | proc drawWireSphere*(radius: GLfloat; slices, stacks: GLint) = 125 | gluQuadricDrawStyle(quadObj, GLU_LINE) 126 | gluQuadricNormals(quadObj, GLU_SMOOTH) 127 | gluSphere(quadObj, radius, slices, stacks) 128 | 129 | proc drawSolidSphere*(radius: GLfloat; slices, stacks: GLint) = 130 | gluQuadricDrawStyle(quadObj, GLU_FILL) 131 | gluQuadricNormals(quadObj, GLU_SMOOTH) 132 | gluSphere(quadObj, radius, slices, stacks) 133 | 134 | proc drawWireCone*(base, height: GLfloat; slices, stacks: GLint) = 135 | gluQuadricDrawStyle(quadObj, GLU_LINE) 136 | gluQuadricNormals(quadObj, GLU_SMOOTH) 137 | gluCylinder(quadObj, base, 0.0, height, slices, stacks) 138 | 139 | proc drawSolidCone*(base, height: GLfloat; slices, stacks: GLint) = 140 | gluQuadricDrawStyle(quadObj, GLU_FILL) 141 | gluQuadricNormals(quadObj, GLU_SMOOTH) 142 | gluCylinder(quadObj, base, 0.0, height, slices, stacks) 143 | 144 | 145 | proc DrawNet*(size: GLfloat, LinesX, LinesZ: GLint) = 146 | beginGL GL_LINES: 147 | for i in 0.. 0: 14 | result = some.free.pop 15 | else: 16 | result = some.next 17 | inc some.next 18 | proc release*[A] (some: var TIDgen[A]; id: A) = 19 | some.free. add id 20 | 21 | 22 | when isMainModule: 23 | var idg = newIDGen[int16]() 24 | 25 | 26 | for i in 0 .. <5: 27 | var i1 = idg.get 28 | assert i == i1.int 29 | for i in countdown(4, 0): 30 | idg.release i.int16 31 | 32 | assert idg.next == 5 33 | assert idg.free == @[4'i16, 3, 2, 1, 0] 34 | -------------------------------------------------------------------------------- /fowltek/importc_block.nim: -------------------------------------------------------------------------------- 1 | import macros, fowltek/macro_dsl 2 | 3 | ## Automatically apply {.importc.} to the following procs (in the future other 4 | ## stuff too, mebbe) 5 | ## importCizzle "box2d": 6 | ## proc Foo() 7 | ## will be changed to 8 | ## proc Foo(){.importc: "box2dFoo".} 9 | 10 | macro importCizzle*(prefixx: string; body: stmt): stmt {.immediate.}= 11 | result = newStmtList() 12 | let prefix = prefixx.strval 13 | 14 | for i in 0..(body.len - 1): 15 | let s = body[i] 16 | 17 | case s.kind 18 | of nnkProcDef: 19 | if s.pragma.kind == nnkEmpty: 20 | s.pragma = newNimNode(nnkPragma) 21 | 22 | 23 | s[4].add(newNimNode(nnkExprColonExpr).add( 24 | !!"importc", newStrLitNode(prefix & $ident(basename(name(s)))))) 25 | 26 | result.add s 27 | 28 | else: 29 | result.add s 30 | 31 | when defined(Debug): result.repr.echo #lul 32 | 33 | -------------------------------------------------------------------------------- /fowltek/macro_dsl.nim: -------------------------------------------------------------------------------- 1 | import strutils,macros 2 | 3 | when false: 4 | proc newEmptyNode*(): PNimrodNode {.compileTime, noSideEffect.} = 5 | ## Create a new empty node 6 | result = newNimNode(nnkEmpty) 7 | 8 | proc newStmtList*(stmts: varargs[PNimrodNode]): PNimrodNode {.compileTime.}= 9 | ## Create a new statement list 10 | result = newNimNode(nnkStmtList).add(stmts) 11 | 12 | proc newBlockStmt*(label: PNimrodNode; body: PNimrodNode): PNimrodNode {.compileTime.} = 13 | ## Create a new block statement with label 14 | return newNimNode(nnkBlockStmt).add(label, body) 15 | proc newBlockStmt*(body: PNimrodNode): PNimrodNode {.compiletime.} = 16 | ## Create a new block: stmt 17 | return newNimNode(nnkBlockStmt).add(newEmptyNode(), body) 18 | 19 | proc newLetStmt*(name, value: PNimrodNode): PNimrodNode{.compiletime.} = 20 | ## Create a new let stmt 21 | return newNimNode(nnkLetSection).add( 22 | newNimNode(nnkIdentDefs).add(name, newNimNode(nnkEmpty), value)) 23 | 24 | proc newAssignment*(lhs, rhs: PNimrodNode): PNimrodNode {.compileTime, inline.} = 25 | return newNimNode(nnkAsgn).add(lhs, rhs) 26 | 27 | proc newDotExpr* (a, b: PNimrodNode): PNimrodNode {.compileTime, inline.} = 28 | ## Create new dot expression 29 | ## a.dot(b) -> `a.b` 30 | return newNimNode(nnkDotExpr).add(a, b) 31 | 32 | 33 | proc newIdentDefs*(name, kind: PNimrodNode; default = newEmptyNode()): PNimrodNode{. 34 | compileTime.} = newNimNode(nnkIdentDefs).add(name, kind, default) 35 | 36 | proc newNilLit*(): PNimrodNode {.compileTime.} = 37 | ## New nil literal shortcut 38 | result = newNimNode(nnkNilLit) 39 | 40 | 41 | proc high*(node: PNimrodNode): int {.compileTime.} = len(node) - 1 42 | ## Return the highest index available for a node 43 | proc last*(node: PNimrodNode): PNimrodNode {.compileTime.} = node[node.high] 44 | ## Return the last item in nodes children. Same as `node[node.high()]` 45 | 46 | 47 | template ProcLikeNodes*:Expr = {nnkProcDef, nnkMethodDef, nnkDo, nnkLambda} 48 | const NoSonsNodes = {nnkNone, nnkEmpty, nnkNilLit, 49 | nnkCharLit .. nnkInt64Lit, nnkFLoatLit .. nnkFloat64Lit, 50 | nnkStrLit .. nnkTripleStrLit, nnkIdent, nnkSym } 51 | 52 | proc ExpectKind*(n: PNimrodNode; k: set[TNimrodNodeKind]) {.compileTime.} = 53 | assert n.kind in k, "Expected one of $1, got $2".format(k, n.kind) 54 | 55 | proc newProc*(name = newEmptyNode(); params: openarray[PNimrodNode] = []; 56 | body: PNimrodNode = newStmtList(), procType = nnkProcDef): PNimrodNode {.compileTime.} = 57 | ## shortcut for creating a new proc 58 | assert procType in ProcLikeNodes 59 | result = newNimNode(procType).add( 60 | name, 61 | newEmptyNode(), 62 | newEmptyNode(), 63 | newNimNode(nnkFormalParams).add(params), ##params 64 | newEmptyNode(), ## pragmas 65 | newEmptyNode(), 66 | body) 67 | 68 | proc copyChildrenTo*(src, dest: PNimrodNode) {.compileTime.}= 69 | ## Copy all children from `src` to `dest` 70 | for i in 0 .. < src.len: 71 | dest.add src[i].copyNimTree 72 | 73 | proc name*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = 74 | someProc.expectKind ProcLikeNodes 75 | result = someProc[0] 76 | proc `name=`*(someProc: PNimrodNode; val: PNimrodNode) {.compileTime.} = 77 | someProc.expectKind ProcLikeNodes 78 | someProc[0] = val 79 | 80 | proc params*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = 81 | someProc.expectKind procLikeNodes 82 | result = someProc[3] 83 | proc `params=`* (someProc: PNimrodNode; params: PNimrodNode) {.compileTime.}= 84 | someProc.expectKind procLikeNodes 85 | assert params.kind == nnkFormalParams 86 | someProc[3] = params 87 | 88 | proc pragma*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = 89 | ## Get the pragma of a proc type 90 | ## These will be expanded 91 | someProc.expectKind procLikeNodes 92 | result = someProc[4] 93 | proc `pragma=`*(someProc: PNimrodNode; val: PNimrodNode){.compileTime.}= 94 | ## Set the pragma of a proc type 95 | someProc.expectKind procLikeNodes 96 | assert val.kind in {nnkEmpty, nnkPragma} 97 | someProc[4] = val 98 | 99 | 100 | template badnodekind(k; f): stmt{.immediate.} = 101 | assert false, "Invalid node kind $# for macros.`$2`" % [$k, f] 102 | 103 | proc body*(someProc: PNimrodNode): PNimrodNode {.compileTime.} = 104 | case someProc.kind: 105 | of procLikeNodes: 106 | return someProc[6] 107 | of nnkBlockStmt, nnkWhileStmt: 108 | return someproc[1] 109 | of nnkForStmt: 110 | return someProc.last 111 | else: 112 | badNodeKind someproc.kind, "body" 113 | 114 | proc `body=`*(someProc: PNimrodNode, val: PNimrodNode) {.compileTime.} = 115 | case someProc.kind 116 | of ProcLikeNodes: 117 | someProc[6] = val 118 | of nnkBlockStmt, nnkWhileStmt: 119 | someProc[1] = val 120 | of nnkForStmt: 121 | someProc[high(someProc)] = val 122 | else: 123 | badNodeKind someProc.kind, "body=" 124 | 125 | 126 | proc `$`*(node: PNimrodNode): string {.compileTime.} = 127 | ## Get the string of an identifier node 128 | case node.kind 129 | of nnkIdent: 130 | result = $node.ident 131 | of nnkStrLit: 132 | result = node.strval 133 | else: 134 | badNodeKind node.kind, "$" 135 | 136 | proc `!`*(a: TNimrodIdent): PNimrodNode {.compileTime, inline.} = newIdentNode(a) 137 | ## Create a new ident node from an identifier 138 | proc `!!`*(a: string): PNimrodNode {.compileTime, inline.} = newIdentNode(a) 139 | ## Create a new ident node from a string 140 | ## The same as !(!(string)) 141 | 142 | when false: 143 | iterator children*(n: PNimrodNode): PNimrodNode {.inline.}= 144 | for i in 0 .. high(n): 145 | yield n[i] 146 | 147 | template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {.immediate, dirty.} = 148 | ## Find the first child node matching condition (or nil) 149 | ## var res = findChild(n, it.kind == nnkPostfix and it.basename.ident == !"foo") 150 | 151 | block: 152 | var result: PNimrodNode 153 | for it in n.children: 154 | if cond: 155 | result = it 156 | break 157 | result 158 | 159 | proc insert*(a: PNimrodNOde; pos: int; b: PNimrodNode) {.compileTime.} = 160 | ## Insert node B into A at pos 161 | if high(a) < pos: 162 | ## add some empty nodes first 163 | for i in high(a)..pos-2: 164 | a.add newEmptyNode() 165 | a.add b 166 | else: 167 | ## push the last item onto the list again 168 | ## and shift each item down to pos up one 169 | a.add(a[a.high]) 170 | for i in countdown(high(a) - 2, pos): 171 | a[i + 1] = a[i] 172 | a[pos] = b 173 | 174 | proc basename*(a: PNimrodNode): PNimrodNode {.compiletime.} = 175 | ## Pull an identifier from prefix/postfix expressions 176 | case a.kind 177 | of nnkIdent: return a 178 | of nnkPostfix, nnkPrefix: return a[1] 179 | else: 180 | quit "Do not know how to get basename of ("& treerepr(a) &")\n"& repr(a) 181 | proc `basename=`*(a: PNimrodNode; val: TNimrodIdent) {.compileTime.}= 182 | case a.kind 183 | of nnkIdent: a.ident = val 184 | of nnkPostfix, nnkPrefix: a[1] = !val 185 | else: 186 | quit "Do not know how to get basename of ("& treerepr(a)& ")\n"& repr(a) 187 | 188 | proc postfix*(node: PNimrodNode; op: string): PNimrodNode {. 189 | compileTime.} = newNimNode(nnkPostfix).add(!!op, node) 190 | proc prefix*(node: PNimrodNode; op: string): PNimrodNode {. 191 | compileTime.} = newNimNode(nnkPrefix).add(!!op, node) 192 | proc infix*(a: PNimrodNode; op: string; b: PNimrodNode): PNimrodNode {. 193 | compileTime.} = newNimNode(nnkInfix).add(!!op, a, b) 194 | 195 | proc unpackPostfix*(node: PNimrodNode): tuple[node: PNimrodNode; op: string] {. 196 | compileTime.} = 197 | node.expectKind nnkPostfix 198 | result = (node[0], $node[1]) 199 | proc unpackPrefix*(node: PNimrodNode): tuple[node: PNimrodNode; op: string] {. 200 | compileTime.} = 201 | node.expectKind nnkPrefix 202 | result = (node[0], $node[1]) 203 | proc unpackInfix*(node: PNimrodNode): tuple[left: PNimrodNode; op: string; right: PNimrodNode] {. 204 | compileTime.} = 205 | assert node.kind == nnkInfix 206 | result = (node[0], $node[1], node[2]) 207 | 208 | proc copy*(node: PNimrodNode): PNimrodNode {.compileTime.} = 209 | ## An alias for copyNimTree() 210 | return node.copyNimTree() 211 | 212 | proc eqIdent* (a, b: string): bool = cmpIgnoreStyle(a, b) == 0 213 | ## Check if two idents are identical 214 | 215 | proc hasArgOfName* (params: PNimrodNode; name: string): bool {.compiletime.}= 216 | ## Search nnkFormalParams for an argument 217 | assert params.kind == nnkFormalParams 218 | for i in 1 .. TMaybe[int] 23 | 24 | template `or`* [T] (a,b: TMaybe[T]): TMaybe[T] = 25 | if a.has: a else: b 26 | 27 | template `or`* [T] (some:TMaybe[T]; right:T): T = 28 | if some.has: some.val else: right 29 | 30 | 31 | template `.?` [T] (a:TMaybe[T]; b): expr = 32 | ## maybe-access operator 33 | ## var my = just(TFoo(x: 1)) 34 | ## my.?x #=> just(1) 35 | if a.has: just(a.val.b) else: nothing[type(a.val.b)]() 36 | 37 | 38 | 39 | 40 | 41 | 42 | when false: 43 | #also since we have mutability we should be able to do these 44 | proc assign*[T] (some: var TMaybe[T]; val: T){.inline.}= 45 | some.val = val 46 | when compiles(isNil(val)): 47 | some.has = not isNil(val) 48 | else: 49 | some.has = true 50 | proc unset* [T] (some: var TMaybe[T]){.inline.} = 51 | reset some.val 52 | some.has = false 53 | 54 | 55 | when isMainModule: 56 | var s = Just("String") 57 | if s: 58 | echo "s is ", s.val 59 | else: 60 | echo "s is nothing" 61 | 62 | var x = Maybe("fux") 63 | if x: echo "x: ", x.val 64 | x = Maybe[string](nil) 65 | if x: echo "x: ", x.val 66 | 67 | var su = 32 68 | ## fatal error because int has no isNil() 69 | #echo(maybe(su)) 70 | 71 | block: 72 | let 73 | a = just 3 74 | b = just 2 75 | c = nothing[int]() 76 | 77 | template echoCode(xpr):stmt = 78 | echo astToStr(xpr),": ", xpr 79 | 80 | echoCode a or c or 5 == 3 81 | echoCode c or 1 == 1 82 | echoCode c or b == just(2) 83 | 84 | type 85 | TFoo = object 86 | zz: int 87 | 88 | proc zoo (some:TFoo): int = 89 | 42 90 | 91 | template ec (xpr): expr = 92 | astToStr(xpr)&" #=> "&($ xpr) 93 | 94 | block: 95 | var x = just(TFoo(zz: 101)) 96 | echo "should be 42: ", ec(x.?zoo) 97 | echo "should be 101: ", ec(x.?zz) 98 | 99 | x = nothing[TFoo]() 100 | echo "should be Nothing: ", ec(x.?zz) 101 | 102 | let foo = x or TFoo(zz:100) 103 | echo "should be 100: ", ec(foo.zz) 104 | 105 | 106 | proc test (): TMaybe[TFoo] = 107 | echo "test() called" 108 | return just(TFoo(zz:33)) 109 | echo ec(just(TFoo()) or test()) 110 | echo ec(nothing[TFoo]() or nothing[TFoo]() or test()) 111 | -------------------------------------------------------------------------------- /fowltek/musings/README.MD: -------------------------------------------------------------------------------- 1 | These projects are unfinished, on hiatus, or WIP 2 | 3 | -------------------------------------------------------------------------------- /fowltek/musings/asteroids.nim: -------------------------------------------------------------------------------- 1 | ## asteroids demo 2 | import math, os, re 3 | import strutils, sequtils, algorithm 4 | randomize() 5 | import fowltek/vector_math 6 | import fowltek/sdl2/engine 7 | import_all_sdl2_modules 8 | 9 | import entitty 10 | entitty_imports 11 | 12 | var engy: TsdlEngine 13 | 14 | type 15 | TVector2f = TVector2[float] 16 | 17 | template ff(some: float, precision = 3): string = formatFloat(some, ffDecimal, precision) 18 | proc `$`*(some: TVector2f): string = "($1,$2)".format(ff(some.x), ff(some.y)) 19 | 20 | 21 | ## messages 22 | proc takeDamage* (amount: int) {.unicast.} 23 | 24 | proc placeAt*(pos: TVector2f) {.unicast.} 25 | proc update*(dt: float){.multicast.} 26 | proc onDeath* {.multicast.} 27 | 28 | proc handleEvent* (event: var TEvent; handled: var bool) {.multicast.} 29 | 30 | proc handleCollision*(withEntity: PEntity) {.unicast.} 31 | 32 | proc draw(R: sdl2.PRenderer) {.multicast.} 33 | 34 | proc debugStr* (collection: var seq[string]) {.multicast.} 35 | proc debugDraw(R: sdl2.PRenderer) {.multicast.} 36 | 37 | var debugDrawDisabled: array[0 .. <100, bool] 38 | template disableDebugDraw(ty): stmt = debugDrawDisabled[componentID(ty)] = true 39 | 40 | 41 | type 42 | Position* = TVector2[float] 43 | 44 | proc pos*[A: TNumber](x, y: A): Position = 45 | result.x = x.float 46 | result.y = y.float 47 | 48 | #defcomponent Position 49 | Position.setInitializer proc(entity: PEntity) = 50 | entity[Position].x = random(640).float 51 | entity[Position].y = random(480).float 52 | msg_impl(Position, placeAt) do (pos: TVector2f): 53 | entity[Position].x = pos.x 54 | entity[Position].y = pos.y 55 | 56 | type 57 | Orientation* = object 58 | angleRadians: float 59 | #defcomponent Orientation 60 | 61 | 62 | proc die(entity: PEntity) 63 | 64 | type 65 | Health = object 66 | hp, max: int 67 | 68 | #defcomponent Health 69 | Health.setInitializer proc(entity: PEntity) = 70 | entity[Health] = Health(hp: 100, max: 100) 71 | 72 | msg_impl(Health, takeDamage) do(amount: int) : 73 | entity[Health].hp -= amount 74 | if entity[Health].hp <= 0: 75 | entity.die 76 | 77 | type Immortal = object 78 | #defcomponent Immortal 79 | 80 | msg_impl(Immortal, takeDamage, 9001) do(amount: int): 81 | #nope 82 | 83 | type 84 | Velocity = object 85 | v: TVector2[float] 86 | max: float 87 | 88 | #defcomponent Velocity 89 | Velocity.requiresComponent Position 90 | 91 | msg_impl(Velocity, update) do(dt: float): 92 | entity[Position] += entity[Velocity].v * dt 93 | 94 | type Friction = object 95 | f: float 96 | #defcomponent Friction 97 | Friction.requiresComponent Velocity 98 | Friction.setInitializer proc(x: PEntity) = 99 | x[Friction].f = 1.0 100 | msg_impl(Friction, update) do(dt: float): 101 | entity[Velocity].v *= pow(entity[Friction].f, dt) 102 | 103 | type 104 | Sprite = object 105 | sprite: PSprite 106 | rect: TRect 107 | 108 | ## Sprite record (a cache is kept) 109 | PSprite = ref object 110 | file: string 111 | tex: PTexture 112 | defaultRect: sdl2.TRect 113 | rows, cols: int 114 | center: TPoint 115 | 116 | proc `$`*(some: Sprite): string = ( 117 | if some.sprite.isNil: "nil" else: some.sprite.file ) 118 | #defcomponent Sprite, "Sprite" 119 | Sprite.requiresComponent Position 120 | 121 | 122 | var spriteCache = initTable[string, pSprite](64) 123 | const imageRoot = "/home/fowl/projects/keineSchweine/data/gfx" 124 | let imageFilenamePattern = re"\S+_(\d+)x(\d+)\.\S{3,4}" 125 | 126 | proc getSprite(R: PRenderer; file: string): PSprite = 127 | result = spriteCache[file] 128 | if result.isNil: 129 | result = PSprite(file: file) 130 | var img = img_load(imageRoot / file) 131 | result.tex = R.createTextureFromSurface(img) 132 | result.defaultRect.w = img.w 133 | result.defaultRect.h = img.h 134 | if file =~ imageFilenamePattern: 135 | result.defaultRect.w = matches[0].parseInt.cint 136 | result.defaultRect.h = matches[1].parseInt.cint 137 | result.center.x = cint(result.defaultRect.w / 2) 138 | result.center.y = cint(result.defaultRect.h / 2) 139 | 140 | result.rows = int(img.h / result.defaultRect.h) 141 | result.cols = int(img.w / result.defaultRect.w) 142 | img.destroy 143 | 144 | spriteCache[file] = result 145 | proc instanceSprite(self: var Sprite; R: PRenderer; file: string) = 146 | self.sprite = R.getSprite(file) 147 | self.rect = self.sprite.defaultRect 148 | Sprite.setInitializer proc(entity: PEntity) = 149 | instanceSprite entity[Sprite], engy, "asteroids/Rock48c_48x48.png" 150 | msg_impl(Sprite, draw) do (R: PRenderer): 151 | var rect = Entity[Sprite].rect 152 | let pos = entity[Position].addr 153 | rect.x = pos.x.cint - entity[Sprite].sprite.center.x 154 | rect.y = pos.y.cint - entity[Sprite].sprite.center.y 155 | 156 | R.copy( 157 | Entity[Sprite].sprite.tex, 158 | Entity[Sprite].rect.addr, 159 | rect.addr ) 160 | 161 | 162 | type 163 | TFrameDelay* = tuple[frame: int, delay: float] 164 | SimpleAnimation = object 165 | timer: float 166 | index: int 167 | frameDelays: seq[TFrameDelay] 168 | animationMode: TAnimationMode 169 | TAnimationMode {.pure.} = enum Loop, Bounce 170 | 171 | proc nFrames* (some: var SimpleAnimation): int {.inline.} = len(some.frameDelays) 172 | proc currentFrame* (some: var SimpleAnimation): var TFrameDelay{. 173 | inline.} = some.frameDelays[some.index] 174 | proc nextFrame* (some: var SimpleAnimation, sprite: var Sprite) {. inline.} = 175 | some.index = (some.index + 1) mod some.nFrames 176 | some.timer = some.currentFrame.delay 177 | sprite.rect.x = cint(sprite.rect.w * some.currentFrame.frame) 178 | 179 | #defcomponent SimpleAnimation 180 | SimpleAnimation.requiresComponent Sprite 181 | SimpleAnimation.setInitializer proc(x: PEntity) = 182 | ## sets up an animation to run through all columns 183 | ## could cache this in spriteCache 184 | let cols = x[Sprite].sprite.cols 185 | let SA = x[SimpleAnimation].addr 186 | newSeq SA.frameDelays, cols 187 | for i in 0.. bounds.right: 239 | pos.x = bounds.x.float 240 | if pos.y.cint < bounds.y: 241 | pos.y = bounds.bottom.float 242 | elif pos.y.cint > bounds.bottom: 243 | pos.y = bounds.y.float 244 | 245 | proc toroidalBounds(x, y, w, h: int): Bounded = 246 | result = newBounded(x,y,w,h) 247 | result.setToroidal 248 | 249 | proc setBouncy(bounds: var Bounded) = 250 | bounds.checkEnt = proc(entity: PEntity; bounds: var Bounded) = 251 | let pos = entity[Position].addr 252 | let vel = entity[Velocity].v.addr 253 | let bounds = bounds.rect.addr 254 | template flipReset(field, toVal): stmt = 255 | pos.field = toVal 256 | vel.field = - vel.field 257 | 258 | if pos.x.cint < bounds.x: 259 | flipReset(x, bounds.x.float) 260 | elif pos.x.cint > bounds.right: 261 | flipReset(x, bounds.right.float) 262 | 263 | if pos.y.cint < bounds.y: 264 | flipReset(y, bounds.y.float) 265 | elif pos.y.cint > bounds.bottom: 266 | flipReset(y, bounds.bottom.float) # """ 267 | proc bouncyBounds(x, y, w, h: int): Bounded = 268 | result = newBounded(x, y, w, h) 269 | result.setBouncy 270 | 271 | msg_impl(Bounded, update) do (dt: float): 272 | entity[Bounded].checkEnt entity, entity[Bounded] 273 | 274 | type 275 | TEventHandler* = proc(entity: PEntity; event: var TEvent; result: var bool) 276 | InputCB* = object 277 | handler: TEventHandler 278 | 279 | proc inputNop (entity: PEntity; event: var TEvent; result: var bool) = nil 280 | 281 | #defcomponent InputCB 282 | InputCB.setInitializer proc(X: PEntity) = 283 | X[InputCB].handler = inputNop 284 | msg_impl(InputCB, handleEvent) do (event: var TEvent; result: var bool): 285 | entity[InputCB].handler(entity, event, result) 286 | 287 | 288 | 289 | type CollisionHandler = object 290 | handler: proc(entity1, entity2: PEntity) 291 | #defcomponent CollisionHandler 292 | CollisionHandler.setInitializer proc(x: PEntity) = 293 | x[CollisionHandler].handler = proc(a,b: PEntity) = nil 294 | msg_impl(CollisionHandler, handleCollision, 1000) do (withEntity: PEntity): 295 | entity[CollisionHandler].handler(entity, withEntity) 296 | 297 | 298 | type 299 | TTurn* {.pure.} = enum 300 | None, Right, Left 301 | TThrust*{.pure.}= enum 302 | Idle, Forward, Reverse 303 | InputState* = object 304 | turning: TTurn 305 | thrust: TThrust 306 | 307 | 308 | proc roll(dir: TTurn) {.unicast.} 309 | 310 | proc add*(some: var Velocity; vector: TVector2f) = 311 | some.v += vector 312 | if some.v.length > some.max: 313 | some.v *= (1.0 - (some.v.length - some.max)) 314 | echo($some.v) 315 | 316 | 317 | proc turn* (dir: TTurn; activate = true) {.unicast.} 318 | proc thrust* (dir: TThrust; activate = true) {.unicast.} 319 | 320 | #defcomponent InputState 321 | InputState.requiresComponent Position, Velocity, Orientation 322 | msg_impl(InputState, turn) do (dir: TTurn; activate: bool): 323 | let s = entity[InputState].addr 324 | if activate: 325 | s.turning = dir 326 | elif s.turning == dir: 327 | s.turning = TTurn.None 328 | msg_impl(InputState, thrust) do(dir: TThrust; activate: bool): 329 | template t : expr = entity[InputState].thrust 330 | if activate: 331 | t = dir 332 | elif entity[InputState].thrust == dir: 333 | t = TThrust.Idle 334 | 335 | msg_impl(InputState, update) do(dt: float): 336 | case entity[InputState].turning 337 | of TTurn.Right: 338 | entity[Orientation].angleRadians += 2.0.degrees2radians 339 | entity.roll TTurn.Right 340 | of TTurn.Left: 341 | entity[Orientation].angleRadians -= 2.0.degrees2radians 342 | entity.roll TTurn.Left 343 | else: nil 344 | case entity[InputState].thrust 345 | of TThrust.Forward: 346 | entity[Velocity].add vectorForAngle(entity[Orientation].angleRadians) 347 | of TThrust.Reverse: 348 | entity[Velocity].add(- vectorForAngle(entity[Orientation].angleRadians)) 349 | else: nil 350 | 351 | 352 | type RollAnimation = object 353 | roll: float 354 | #defcomponent RollAnimation 355 | RollAnimation.requiresComponent Sprite, Orientation 356 | #RollAnimation.conflictsWith SimpleAnimation 357 | 358 | msg_impl(RollAnimation, roll) do(dir: TTurn): 359 | let amount = if dir == TTurn.right: -0.1 else: 0.1 360 | entity[RollAnimation].roll += amount 361 | if entity[RollAnimation].roll > 1: entity[RollAnimation].roll = 1 362 | elif entity[RollAnimation].roll < -1: entity[RollAnimation].roll = -1 363 | 364 | msg_impl(RollAnimation, update) do(dt: float): 365 | let spr = entity[Sprite].addr 366 | # in a roll sprite the rows are angles 367 | let row = ((entity[Orientation].angleRadians.radians2degrees / 360.0) * entity[Sprite].sprite.rows.float).int 368 | entity[Sprite].rect.y = cint(row * entity[Sprite].rect.h) 369 | let cols = entity[Sprite].sprite.cols 370 | let midCol = floor(cols / 2) 371 | #echo "midcol is ", midcol.int 372 | #echo "calculated column is ", cint(midCol + (midCol * entity[RollAnimation].roll)) 373 | #echo "roll is ", ff(entity[RollAnimation].roll) 374 | entity[Sprite].rect.x = cint(midCol + (midCol * entity[RollAnimation].roll)) * entity[Sprite].sprite.defaultRect.w 375 | #entity[Sprite].rect.x = cint(col * entity[Sprite].rect.w) 376 | entity[RollAnimation].roll *= 0.9 377 | 378 | 379 | template debugStrImpl(ty): stmt = 380 | msg_impl(ty, debugStr) do(result: var seq[string]): 381 | result.add "$#: $#".format(ComponentInfo(ty).name, entity[ty]) 382 | debugStrImpl(Health) 383 | debugStrImpl(Position) 384 | debugStrImpl(Velocity) 385 | debugStrImpl(Sprite) 386 | 387 | proc debugStr*(entity: PEntity): seq[string] {.inline.}= 388 | result = @[] 389 | entity.debugStr(result) 390 | 391 | var 392 | EM = newEntityManager() 393 | entities = newSeq[TEntity](0) 394 | 395 | proc `$`* [T] (some: seq[T]): string = "[$#]".format(some.map(proc(x: T): string = $x).join(", ")) 396 | 397 | var reaper: tuple[souls: seq[int]] 398 | reaper.souls = @[] 399 | proc reap = 400 | if len(reaper.souls) > 0: 401 | reaper.souls = distnct(reaper.souls) 402 | reaper.souls.sort cmp[int] 403 | #echo "reaping ", reaper.souls.len, " souls ", reaper.souls 404 | for i in countdown( 0) 458 | Layer1, Layer2, Layer3, Layer4, Layer5, Layer6 459 | TCollisionDiscriminant* = tuple[group: int, layers: set[TLayer]] 460 | 461 | BoundingCircle = object 462 | discriminant: TCollisionDiscriminant 463 | radius: float 464 | 465 | #defcomponent BoundingCircle 466 | BoundingCircle.requiresComponent Position 467 | 468 | proc checkCollision*(entity2: PEntity): bool {.unicast.} 469 | msg_impl(BoundingCircle, checkCollision) do(entity2: PEntity) -> bool: 470 | result = entity[Position].distance(entity2[Position]) < entity[BoundingCircle].radius + entity2[BoundingCircle].radius 471 | if result: 472 | let disc = (e1: entity[BoundingCircle].discriminant.addr, e2: entity2[BoundingCircle].discriminant.addr) 473 | if(;var g1 = entity[BoundingCircle].discriminant.group; var g2 = entity2[BoundingCircle].discriminant.group; g1+g2 > 0 and g1 == g2): 474 | return false 475 | for L in entity[BoundingCircle].discriminant.layers: 476 | if L in entity2[BoundingCircle].discriminant.layers: return true 477 | 478 | debugDrawImpl(BoundingCircle): 479 | let pos = entity[Position].addr 480 | let radius = entity[BoundingCircle].addr 481 | R.circleRGBA pos.x.int16, pos.y.int16, radius.radius.int16, 255,0,0,255 482 | 483 | msg_impl(Health, handleCollision) do(withEntity: PEntity): 484 | entity.takeDamage 1 485 | 486 | 487 | 488 | disableDebugDraw Velocity 489 | disableDebugDraw Position 490 | disableDebugDraw BoundingCircle 491 | 492 | ## https://github.com/Araq/Nimrod/issues/431 493 | echo "Number of unicast messages: ", numMessages, " should be about 10 " 494 | echo "Number of components: ", numComponents, " should be more than 10 (compile with -d:debug to see all declared)" 495 | 496 | proc randf* (precision = 10_000): float = random(precision)/precision 497 | 498 | proc randomizeVelocity*(ent: PEntity, length: float) = 499 | ent[Velocity].v = vectorForAngle(random(360).float.degrees2radians) * length 500 | Velocity.setInitializer proc(x: PEntity) = randomizeVelocity(x, randf() * 5.0) 501 | 502 | type TAsteroidRecord = tuple[ 503 | radius: float, file: string, deathSpawner: proc(x: PEntity)] 504 | 505 | proc newAsteroidRecord ( 506 | radius = 10.0, file = "Rock24a_24x24.png", spawnOnDeath: openarray[int] = []): TAsteroidRecord 507 | 508 | let asteroids = [ 509 | newAsteroidRecord(radius = 12.0, file = "Rock24a_24x24.png"), 510 | newAsteroidRecord(radius = 12.0, file = "Rock24b_24x24.png"), 511 | newAsteroidRecord(radius = 16.0, file = "Rock32a_32x32.png"), 512 | newAsteroidRecord(radius = 20.0, file = "Rock48a_48x48.png", spawnOnDeath = [0,1,2]), #3 513 | newAsteroidRecord(radius = 20.0, file = "Rock48b_48x48.png", spawnOnDeath = [3,3,2]), 514 | newAsteroidRecord(radius = 22.0, file = "Rock48c_48x48.png", spawnOnDeath = [3,3,2]), #5 515 | newAsteroidRecord(radius = 26.0, file = "Rock64a_64x64.png", spawnOnDeath = [4,5,3]), 516 | newAsteroidRecord(radius = 24.0, file = "Rock64b_64x64.png", spawnOnDeath = [6,5,4]), #7 517 | newAsteroidRecord(radius = 22.0, file = "Rock64c_64x64.png", spawnOnDeath = [7,6,5]) 518 | ] 519 | 520 | proc mkAsteroid(id = asteroids.len.random): var TEntity {.discardable.} = 521 | entities.add(em.newEntity( 522 | Position, Velocity, Health, Bounded, BoundingCircle, SimpleAnimation, Sprite, DeathCallback)) 523 | let 524 | idx = asteroids.len.random 525 | file = "asteroids" / asteroids[idx][1] 526 | template lastEnt : expr = entities[< entities.len] 527 | result = lastEnt 528 | 529 | result[BoundingCircle].radius = asteroids[idx].radius 530 | result[BoundingCircle].discriminant.layers.incl Layer1 531 | instanceSprite(result[Sprite], engy.render, file) 532 | result[DeathCallback].cb = asteroids[idx].deathSpawner 533 | 534 | proc newAsteroidRecord ( 535 | radius: float, file: string, spawnOnDeath: openarray[int]): TAsteroidRecord = 536 | result.radius = radius 537 | result.file = file 538 | let spawnOnDeath = @spawnOnDeath 539 | result.deathSpawner = proc(x: PEntity) = 540 | if entities.len < 100: 541 | for ast_id in spawnOnDeath: 542 | let ast = mkAsteroid(ast_id).addr 543 | ast[].place_at(x[Position]) 544 | ast[].randomizeVelocity 4.2 545 | 546 | 547 | var the_mouse = newEntity(em, Position, BoundingCircle, Immortal, InputCB, 548 | DebugInfoDisp, CollisionHandler) 549 | the_mouse[BoundingCircle].radius = 4.0 550 | the_mouse[InputCB].handler = proc(x: PEntity; event: var TEvent; result: var bool) = 551 | if event.kind == MouseMotion: 552 | let m = evMouseMotion(event) 553 | the_mouse[Position] = pos(m.x, m.y) 554 | result = true 555 | the_mouse[CollisionHandler].handler = proc(self: PEntity; withEntity: PEntity) = 556 | self[DebugInfoDisp].result.setLen 0 557 | withEntity.debugStr self[DebugInfoDisp].result 558 | ## the info is drawn from DebugInfoDisp#debugDraw 559 | entities.add the_mouse 560 | 561 | 562 | for i in 0.. <10: mkAsteroid() 563 | var player = newEntity(em, Position, Velocity, BoundingCircle, 564 | Sprite, Immortal, Bounded, RollAnimation, Orientation, InputState, 565 | InputCB, Friction) 566 | #player[BoundingCircle].discriminant.layers.incl Layer1 567 | player[Sprite].instanceSprite engy, "ships/terran/hornet_54x54.png" 568 | player[Friction].f = 0.98 569 | 570 | player[InputCB].handler = proc(x: PEntity; event: var sdl2.TEvent; result: var bool) = 571 | case event.kind 572 | of keyDown: 573 | let k = evKeyboard(Event) 574 | case k.keysym.sym 575 | of K_Left: 576 | x.turn TTurn.Left 577 | of K_Right: 578 | x.turn TTurn.Right 579 | of K_Up: 580 | x.thrust TThrust.Forward 581 | of K_Down: 582 | x.thrust TThrust.Reverse 583 | 584 | else: nil 585 | of keyUP: 586 | let k = evKeyboard(event) 587 | case k.keysym.sym 588 | of K_Left: 589 | x.turn TTurn.Left,false 590 | of K_Right: 591 | x.turn TTurn.Right,false 592 | of K_UP: 593 | x.thrust TThrust.Forward,false 594 | of K_DOWN: 595 | x.thrust TThrust.Reverse,false 596 | else: nil 597 | else: nil 598 | 599 | 600 | entities.add player 601 | 602 | template eachEntity(body: stmt): stmt {.immediate.} = 603 | for e_id in 0 .. > ", L 206 | template debugOutgoing(L): stmt = 207 | when defined(Debug): 208 | echo "<< ", L 209 | 210 | proc sendLine* (client: PClient; line: string) {.inline.} = 211 | client.sock.send line 212 | client.sock.send "\c\L" 213 | debugOutgoing line 214 | 215 | proc send* (client: PClient; str: varargs[string]){.inline.}= 216 | for s in str: 217 | client.sock.send s 218 | client.sock.send "\c\L" 219 | 220 | proc serverNotice* (client: PClient; msg: string) = 221 | client.send "NOTICE * :", msg 222 | 223 | proc parseCommand(cmd: string): tuple[prefix, command: string, args: seq[string]]= 224 | const whitespace = {' ','\t'} 225 | var i = 0 226 | 227 | if cmd[i] == ':': 228 | inc i 229 | inc i, cmd.parseUntil(result.prefix, whitespace, i) 230 | inc i 231 | else: 232 | result.prefix = "" 233 | inc i, cmd.parseUntil(result.command, whitespace, i) 234 | 235 | result.args = @[] 236 | while cmd[i] in whitespace: 237 | inc i 238 | if cmd[i] in {':','\0'}: break 239 | 240 | result.args.setLen result.args.len+1 241 | inc i, cmd.parseUntil(result.args[result.args.len - 1], {' ','\t','\0'}, i) 242 | 243 | if cmd[i] == ':': 244 | result.args.add cmd[i+1 .. cmd.high] 245 | 246 | when false: 247 | proc parseCommand(cmd: string): seq[string] = 248 | result = @[] 249 | var i = cmd.find(' ') 250 | result.add cmd[0 .. 1: 385 | keys = args[1].split(',') 386 | for i in 0 .. high(channels): 387 | serv.joinChan( 388 | client, 389 | channels[i], 390 | if not(keys.isNil) and i < keys.len: keys[i] 391 | else: nil 392 | ) 393 | 394 | of "CAP": 395 | # http://www.leeh.co.uk/draft-mitchell-irc-capabilities-02.html 396 | else: 397 | # 398 | 399 | proc newClient* (sock: PAsyncSocket; host: string): PClient {. 400 | inline.} = PClient(sock: sock, host: host, nick: "", user: "") 401 | 402 | proc newServer* (port = 6667.TPort; buffered = true; name = "Disparity"): PServer = 403 | result = PServer( 404 | name: name, 405 | host: gethostname(), 406 | disp: newDispatcher(), 407 | sock: AsyncSocket(buffered = buffered, typ = SOCK_STREAM), 408 | clients: initTable[PAsyncSocket, PClient](512), 409 | nicks: initTable[string, PClient](512), 410 | channels: initTable[string, TChannel](512) 411 | ) 412 | 413 | let serv = result 414 | let disp = result.disp 415 | result.sock.handleAccept = proc(s: PAsyncSocket) = 416 | var client = new(TAsyncSocket) 417 | var addy: string 418 | s.acceptAddr client, addy 419 | 420 | client.handleRead = handleRead(serv) 421 | disp.register client 422 | serv.clients[client] = newClient(client, getHostByAddr(addy).name) 423 | 424 | 425 | result.disp.register result.sock 426 | result.sock.bindAddr port 427 | result.sock.listen 428 | 429 | echo "Listening on port ", port.int, ".." 430 | 431 | proc loop* (serv: PServer) = 432 | serv.running = true 433 | while serv.running: 434 | if not serv.disp.poll(): 435 | serv.running = false 436 | proc run* (serv: PServer) = 437 | try: 438 | serv.loop 439 | finally: 440 | serv.sock.close 441 | echo "Closed socket." 442 | 443 | when isMainModule: 444 | var port = 1776.TPort 445 | import parseopt 446 | for kind, k,v in getOpt(): 447 | case kind 448 | of cmdLongOption,cmdShortOption: 449 | case k 450 | of "p", "port": 451 | port = v.parseInt.TPort 452 | else: 453 | echo "Unrecognized option: ", k 454 | else: 455 | echo "What option is this? ", k 456 | 457 | var s = newServer(port = port) 458 | setControlCHook proc{.noConv.} = 459 | s.running = false 460 | echo "Interrupt shutdown!" 461 | 462 | s.run 463 | 464 | 465 | -------------------------------------------------------------------------------- /fowltek/musings/ircd_hostname.nim: -------------------------------------------------------------------------------- 1 | proc getHostname* : string {.raises: [EIO].} 2 | 3 | when defined(LINUX): 4 | import posix 5 | 6 | proc getHostname : string = 7 | var hostname_t: array[0 .. <256, char] 8 | var hostname = hostname_t[0].addr 9 | if gethostname(hostname, 256) != 0: 10 | return "" 11 | 12 | var hints: TAddrInfo 13 | var info: ptr TAddrInfo 14 | hints.ai_family = AF_UNSPEC 15 | hints.ai_socktype = SOCK_STREAM 16 | hints.ai_flags = AI_CANONNAME 17 | 18 | let res = getaddrinfo(hostname, nil, hints.addr, info) 19 | if res != 0: 20 | raise newException(system.EIO, "getaddrinfo: "& $gai_strerror(res)) 21 | 22 | when true: 23 | result = $info.ai_canonname 24 | else: 25 | #is this useful? 26 | var p = info 27 | while not p.isNil: 28 | echo "hostname: ", p.ai_canonname 29 | p = p.ai_next 30 | 31 | freeaddrinfo info 32 | 33 | 34 | when isMainModule: 35 | echo "This hostname: ", getHostname() 36 | -------------------------------------------------------------------------------- /fowltek/musings/nim3d/examples/LiberationMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fowlmouth/nimlibs/c8db2ab0acc505d63f26c15d525e01fa970a8cf6/fowltek/musings/nim3d/examples/LiberationMono-Regular.ttf -------------------------------------------------------------------------------- /fowltek/musings/nim3d/examples/cube.ply: -------------------------------------------------------------------------------- 1 | ply 2 | format ascii 1.0 3 | comment made by anonymous 4 | comment this file is a cube 5 | element vertex 8 6 | property float32 x 7 | property float32 y 8 | property float32 z 9 | element face 6 10 | property list uint8 int32 vertex_index 11 | end_header 12 | 0 0 0 13 | 0 0 1 14 | 0 1 1 15 | 0 1 0 16 | 1 0 0 17 | 1 0 1 18 | 1 1 1 19 | 1 1 0 20 | 4 0 1 2 3 21 | 4 7 6 5 4 22 | 4 0 4 5 1 23 | 4 1 5 6 2 24 | 4 2 6 7 3 25 | 4 3 7 4 0 -------------------------------------------------------------------------------- /fowltek/musings/nim3d/examples/nimrod.cfg: -------------------------------------------------------------------------------- 1 | path = "../lib" ##nim3d 2 | path = "../../../../nimrod-glfw/src" 3 | path = "../../../pure" 4 | path = "../../../macros" 5 | path = "../../../wrappers/ode" 6 | path = "../../../wrappers/ftgl" 7 | path = "../../../wrappers/devil" 8 | path = "../../../wrappers/assimp" 9 | define = UseDevil 10 | define = UseODE 11 | define = UseFTGL -------------------------------------------------------------------------------- /fowltek/musings/nim3d/examples/testapp.nim: -------------------------------------------------------------------------------- 1 | import 2 | opengl, glfw, 3 | baseapp, gl_helpers, camera, nodes, textnode 4 | var 5 | game: PApp 6 | 7 | game = newApp(640, 480) 8 | 9 | game.setUpdate proc(dt: float) = 10 | if keystate[key('W')]: 11 | game.getCamera.moveForward(-2.0) 12 | elif keyState[key('S')]: 13 | game.getCamera.moveForward(2.0) 14 | if keystate[key('A')]: 15 | game.getCamera.strafeRight(2.0) 16 | elif keystate[key('D')]: 17 | game.getCamera.strafeRight(-2.0) 18 | 19 | 20 | game.setRender proc() = 21 | game.renderScene() 22 | discard """glColor3f 0.0, 1.0, 0.0 23 | drawWireCube(20.0)""" 24 | 25 | var scn = newScene() 26 | game.setScene scn 27 | 28 | block: 29 | let colors = [ 30 | colorf(0.0, 0.0, 1.0), colorf(0.0, 1.0, 0.0), colorf(1.0, 0.0, 0.0)] 31 | let variance = 10 32 | for i in 0..2: 33 | let v = (variance * i) - variance 34 | var cube = newWireCube(3.0, colors[i]) 35 | cube.setPosition vec3f(v, 0, 0) 36 | scn.add cube 37 | var s = newWireSphere(3.0, colors[0]) 38 | s.setPosition vec3f(0, -10, 0) 39 | scn.add s 40 | 41 | block: 42 | var cam = game.getCamera() 43 | cam.setPosition vec3f(0, 0, 120) 44 | cam.setTarget vec3f(0, 0, 0) 45 | 46 | var to = newTextNode("helloooo", "LiberationMono-Regular.ttf", 24) 47 | to.setPosition vec3f(100, 0, 0) 48 | scn.add(to) 49 | 50 | to = newTextNode(":>") 51 | to.setPosition vec3f(-100, 0, 0) 52 | scn.add to 53 | 54 | 55 | game.run() 56 | -------------------------------------------------------------------------------- /fowltek/musings/nim3d/examples/testmodel.nim: -------------------------------------------------------------------------------- 1 | import 2 | opengl, glfw, 3 | baseapp, gl_helpers, camera, nodes, textnode, 4 | assimp, unsigned, models, vector_math, math 5 | var 6 | game = newApp(640, 480) 7 | var1 = 0.0 8 | 9 | 10 | 11 | 12 | game.setRender proc() = 13 | game.renderScene() 14 | 15 | 16 | block: 17 | var cam = game.getCamera() 18 | cam.setPosition vec3f(0, 0, 300) 19 | cam.setTarget vec3f(0, 0, 0) 20 | 21 | 22 | var m = newModel("ak47.obj") 23 | if not m.isNil: 24 | m.setPosition vec3f(-70, 0, 0) 25 | m.scale *= 20.0 26 | game.getScene.add m 27 | 28 | game.setUpdate proc(dt: float) = 29 | if keystate[key('W')]: 30 | game.getCamera.moveForward(-2.0) 31 | elif keyState[key('S')]: 32 | game.getCamera.moveForward(2.0) 33 | if keystate[key('A')]: 34 | game.getCamera.strafeRight(2.0) 35 | elif keystate[key('D')]: 36 | game.getCamera.strafeRight(-2.0) 37 | 38 | if not m.isNil: 39 | var1 = (var1 + 23.0 * dt) mod 360.0 40 | m.rot.y = var1 41 | 42 | 43 | game.run() 44 | -------------------------------------------------------------------------------- /fowltek/musings/nim3d/lib/baseapp.nim: -------------------------------------------------------------------------------- 1 | import glfw, gl_helpers, opengl, 2 | strutils, camera, nodes 3 | when defined(UseDevil): 4 | import devil, ilut 5 | type 6 | PApp* = ref TApp 7 | TApp* = object 8 | w, h: int32 9 | activeInput: PInputClient 10 | cam: PCamera 11 | scene: PScene 12 | renderProc: TRenderCallback 13 | updateProc: TUpdateCallback 14 | 15 | PInputClient* = ref TInputClient 16 | TInputClient* = object 17 | keyHandlers: array[TKeyAction, array[0..GLFW_KEY_LAST, TKeyHandler]] 18 | 19 | TKeyHandler* = proc() {.closure.} 20 | TRenderCallback* = proc(){.closure.} 21 | TUpdateCallback* = proc(dt:float){.closure.} 22 | var 23 | keyState*: array[0..GLFW_KEY_LAST, bool] 24 | instance: PApp 25 | 26 | proc newInputClient*(): PInputClient 27 | proc handleWindowSize(w, h: cint){.stdcall.} 28 | proc handleKey(key: cint, status: TKeyAction){.stdcall.} 29 | proc setCamera*(a: PApp; cam: PCamera) {.inline.} 30 | proc setScene*(a: PApp; scn: PScene) {.inline.} 31 | 32 | template KEY*(c: char): cint = cint(c) 33 | 34 | proc newApp*(w, h: int32; antiAlias = 4'i32): PApp = 35 | if not instance.isNil: 36 | quit "App already instanced" 37 | 38 | if not glfw.Init().bool: 39 | quit "Could not initialize GLFW!" 40 | 41 | new result 42 | instance = result 43 | result.w = w 44 | result.h = h 45 | result.activeInput = newInputClient() 46 | result.setCamera newCamera() 47 | result.setScene newScene() 48 | 49 | when defined(UseDevil): 50 | IL_init() 51 | ILUT_init() 52 | if not ILUT_renderer(ILUT_OPENGL): 53 | quit "Failed to initialize Devil!" 54 | 55 | OpenWindowHint(GLFW_FSAA_SAMPLES, antiAlias) 56 | 57 | if not OpenWindow(w, h, 8, 8, 8, 8, 0, 0, GLFW_WINDOW).bool: 58 | Terminate() 59 | quit "Failed to open window" 60 | 61 | opengl.loadExtensions() 62 | gl_helpers.init() 63 | 64 | glEnable GL_LIGHTING 65 | glEnable GL_LIGHT0 66 | 67 | glEnable GL_DEPTH_TEST 68 | 69 | glLightModeli GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE 70 | glEnable GL_NORMALIZE 71 | 72 | SwapInterval(1) 73 | 74 | setWindowSizeCallback handleWindowSize 75 | setKeyCallback handleKey 76 | 77 | proc setRender*(a: PApp; render: TRenderCallback) = 78 | a.renderProc = render 79 | proc setUpdate*(a: PApp; update: TUpdateCallback) = 80 | a.updateProc = update 81 | 82 | proc getCamera*(a: PApp): PCamera {.inline.} = a.cam 83 | proc setCamera*(a: PApp; cam: PCamera) = 84 | a.cam = cam 85 | proc getScene*(a: PApp): PScene {.inline.} = a.scene 86 | proc setScene*(a: PApp; scn: PScene) = a.scene = scn 87 | 88 | proc newInputClient*(): PInputClient = 89 | new result 90 | 91 | proc windowOpen*(): bool {.inline.} = GetWindowParam(GLFW_OPENED) == GL_TRUE 92 | 93 | method update*(app: PApp; dt: float) = 94 | if not(app.updateProc.isNil): app.updateProc(dt) 95 | method render*(app: PApp) = 96 | glClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT 97 | app.cam.apply() 98 | if not(app.renderProc.isNil): app.renderProc() 99 | SwapBuffers() 100 | 101 | method renderScene*(app: PApp) = app.scene.render() 102 | 103 | method run*(app: PApp) = 104 | var currentTime, lastTime = glfw.getTime() 105 | lastTime -= (16 / 1000) ##fix so that ode doesnt derp 106 | when defined(ShowFPS): 107 | var FPStime = currentTime + 1.0 108 | while windowOpen(): 109 | currentTime = glfw.getTime() 110 | when defined(ShowFPS): 111 | if currentTime > FPStime: 112 | setWindowTitle "FPS: "&formatFloat(1.0/(currentTime - lastTime), ffDecimal, 2) 113 | FPStime = currentTime + 1.0 114 | app.update(currentTime - lastTime) 115 | app.render() 116 | lastTime = currentTime 117 | 118 | proc register*(client: PInputClient; key: cint; 119 | kind: TKeyAction; p: TKeyHandler) = 120 | client.keyHandlers[kind][key] = p 121 | 122 | proc register*(app: PApp; key: cint; 123 | kind: TKeyAction; p: TKeyHandler) {.inline.} = 124 | app.activeInput.register(key, kind, p) 125 | 126 | proc setInputClient*(app: PApp; client: PInputClient){.inline.}= 127 | app.activeInput = client 128 | 129 | proc handleKey(key: cint, status: TKeyAction) = 130 | keyState[key] = status.bool 131 | let p = instance.activeInput.keyHandlers[status][key] 132 | if not p.isNil: p() 133 | 134 | proc handleWindowSize(w, h: cint) = 135 | instance.w = w 136 | instance.h = h 137 | 138 | glViewport 0, 0, w, h 139 | glMatrixMode GL_PROJECTION 140 | glLoadIdentity() 141 | 142 | gluPerspective 80.0, w / h, 0.1, 1000.0 143 | 144 | 145 | -------------------------------------------------------------------------------- /fowltek/musings/nim3d/lib/camera.nim: -------------------------------------------------------------------------------- 1 | import gl_helpers, opengl, vector_math, nodes 2 | type 3 | PCamera* = ref TCamera 4 | TCamera* = object 5 | pos*, target, up: TVector3f 6 | moveSpeed: TVector3f 7 | targetNode: PNode 8 | 9 | proc newCamera*(): PCamera = 10 | new result 11 | result.up = vec3f(0.0, 1.0, 0.0) 12 | result.moveSpeed.z = -1.0 13 | 14 | proc lookAt*(c: PCamera; n: PNode) = 15 | c.target = n.getPosition() 16 | proc target*(c: PCamera; n: PNode) = 17 | c.targetNode = n 18 | 19 | method apply*(c: PCamera) = 20 | if not(c.targetNode.isNil): 21 | c.lookAt(c.targetNode) 22 | 23 | glMatrixMode GL_MODELVIEW 24 | glLoadIdentity() 25 | 26 | gluLookat(c.pos.x, c.pos.y, c.pos.z, c.target.x, c.target.y, c.target.z, 27 | c.up.x, c.up.y, c.up.z) 28 | 29 | proc getPosition*(c: PCamera): TVector3f = c.pos 30 | proc setPosition*(c: PCamera; pos: TVector3f) = c.pos = pos 31 | proc getTarget*(c: PCamera): var TVector3f = c.target 32 | proc setTarget*(c: PCamera; pos: TVector3f){.inline.} = c.getTarget() = pos 33 | 34 | proc moveForward*(c: PCamera; by: float) = 35 | let dir = (c.target - c.pos).normalize * -by 36 | c.pos += dir 37 | c.target += dir 38 | 39 | proc strafeRight*(c: PCamera; by: float) = 40 | let dir = (c.target - c.pos).normalize.cross(c.up) * -by 41 | c.pos += dir 42 | c.target += dir 43 | -------------------------------------------------------------------------------- /fowltek/musings/nim3d/lib/ftgl_manager.nim: -------------------------------------------------------------------------------- 1 | import ftgl, tables 2 | 3 | type TFontKey* = tuple[name: string; size: int32] 4 | var fonts = initTable[TFontKey, PFont](16) 5 | 6 | proc cleanup*() = 7 | for key in keys(fonts): 8 | fonts[key].destroy() 9 | fonts.del key ## tested this, its kosher. 10 | 11 | proc getFont*(filename: string; size: int32): PFont = 12 | result = fonts[(filename, size)] 13 | if not result.isNil: 14 | return 15 | 16 | result = createTextureFont(filename) 17 | if not result.setFaceSize(size.cuint, size.cuint): 18 | echo "Failed to set face size!" 19 | ## what should happen here? meh 20 | 21 | fonts[(filename, size)] = result 22 | 23 | -------------------------------------------------------------------------------- /fowltek/musings/nim3d/lib/models.nim: -------------------------------------------------------------------------------- 1 | import 2 | nodes, opengl, assimp, gl_helpers, pointer_arithm 3 | 4 | type 5 | PModel* = ref TModel 6 | TModel* = object of nodes.TNode 7 | aiScene: assimp.PScene 8 | glList: GLuint 9 | 10 | 11 | proc apply_material(mtl: PMaterial) = 12 | ##foo 13 | 14 | proc recursiveRender(scn: assimp.PScene; node: assimp.PNode) = 15 | var matrix = node.transformation 16 | (addr matrix).transpose 17 | 18 | pushMatrixGL: 19 | glMultMatrixf(addr matrix[0]) 20 | for i in 0.. 0: 69 | newSeq result.weights[i], L 70 | for j in 0 ..