planetis-m / naylib

Yet another raylib Nim wrapper
MIT License
209 stars 11 forks source link

Use concepts for drop-in vectors #72

Closed beef331 closed 1 year ago

beef331 commented 1 year ago

Whoops thought this through and it's not sane(accidentally submitted the issue before finished writing).

planetis-m commented 1 year ago

I wish that was possible. Anyway thanks for confirming I'm not totally insane.

beef331 commented 1 year ago

Well it's possible one way, the otherway is not really, though a template could exist like template emitConverter(T: typedesc[Vec2]) = ...

type
  MyVec = object
    x, y: float32

  Vec2 = concept v
    v.x is float32
    v.y is float32
    not compiles(v.z)

proc doThing(v: MyVec) = echo v

when defined(naylibConverters) or true:
  converter toMyVec(v: Vec2): MyVec =
    mixin x, y
    MyVec(x: v.x, y: v.y)

  template emitConverter(T: typedesc[Vec2]): untyped = 
    converter toVec*(v: MyVec): T =
      mixin T
      T.init(v.x, v.y)

type 
  MyOtherVec = object
    x, y: float32
  MyOthererVec = tuple[x, y: float32]
  ArrVec = array[2, float32]

proc `x`(arrVec: ArrVec): float32 = arrVec[0]
proc `y`(arrVec: ArrVec): float32 = arrVec[1]

proc init(_: typedesc[MyOtherVec], x, y: float32): MyOtherVec = MyOtherVec(x: x, y: y)
proc init(_: typedesc[MyOthererVec], x, y: float32): MyOthererVec = MyOthererVec (x, y)
proc init(_: typedesc[ArrVec], x, y: float32): ArrVec = [x, y]

MyOtherVec.init(10, 20).doThing()
MyOthererVec.init(10, 20).doThing()
ArrVec.init(10, 20).doThing()

emitConverter(MyOtherVec)
emitConverter(MyOthererVec)
emitConverter(ArrVec)

var 
  a: ArrVec = MyVec(x: 100, y: 200)
  b: MyOtherVec = MyVec(x: 200, y: 300)
  c: MyOthererVec = MyVec(x: 200, y: 300)

Sadly this is all we can do.

If you do want to go down concept paths https://github.com/beef331/truss3d/blob/master/src/truss3D/mathtypes.nim is a good reference for math types.