canvas.nim 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. # author: Ethosa
  2. import
  3. math,
  4. ../thirdparty/opengl,
  5. ../core/vector2,
  6. ../core/color,
  7. ../core/anchor,
  8. node
  9. const PI2 = PI + PI
  10. type
  11. DrawCommandType* {.size: sizeof(int8).} = enum
  12. POINT, LINE, RECT, FILL, CIRCLE
  13. DrawCommand* = object
  14. x1*, y1*: GLfloat
  15. color*: ColorRef
  16. case kind*: DrawCommandType
  17. of LINE, RECT:
  18. x2*, y2*: GLfloat
  19. of CIRCLE:
  20. points*: seq[GLfloat]
  21. else:
  22. discard
  23. CanvasObj* = object of NodeObj
  24. commands*: seq[DrawCommand]
  25. CanvasPtr* = ptr CanvasObj
  26. proc Canvas*(name: string, variable: var CanvasObj): CanvasPtr =
  27. ## Creates a new Canvas pointer.
  28. ##
  29. ## Arguments:
  30. ## - `name` is a node name.
  31. ## - `variable` is a CanvasObj variable
  32. runnableExamples:
  33. var
  34. canvas1_obj: CanvasObj
  35. canvas1 = Canvas("Canvas", canvas1_obj)
  36. ## Creates a new Canvas pointer.
  37. nodepattern(CanvasObj)
  38. variable.rect_size.x = 40
  39. variable.rect_size.y = 40
  40. proc Canvas*(variable: var CanvasObj): CanvasPtr {.inline.} =
  41. ## Creates a new Canvas pointer with default name "Canvas".
  42. ##
  43. ## Arguments:
  44. ## - `variable` is a CanvasObj variable
  45. runnableExamples:
  46. var
  47. canvas1_obj: CanvasObj
  48. canvas1 = Canvas(canvas1_obj)
  49. Canvas("Canvas", variable)
  50. proc calculateX(canvas: CanvasPtr, x, gx: GLfloat): GLfloat =
  51. if x > canvas.rect_size.x + gx:
  52. canvas.rect_size.x + gx
  53. elif x < gx:
  54. gx
  55. else:
  56. x
  57. proc calculateY(canvas: CanvasPtr, y, gy: GLfloat): GLfloat =
  58. if y < gy - canvas.rect_size.y:
  59. gy - canvas.rect_size.y
  60. elif y > gy:
  61. gy
  62. else:
  63. y
  64. method draw*(canvas: CanvasPtr, w, h: GLfloat) =
  65. ## This uses in the `window.nim`.
  66. canvas.calcGlobalPosition()
  67. let
  68. x = -w/2 + canvas.global_position.x
  69. y = h/2 - canvas.global_position.y
  70. for cmd in canvas.commands:
  71. case cmd.kind:
  72. of POINT:
  73. glBegin(GL_POINTS)
  74. glColor4f(cmd.color.r, cmd.color.g, cmd.color.b, cmd.color.a)
  75. glVertex2f(canvas.calculateX(x + cmd.x1, x), canvas.calculateY(y - cmd.y1, y))
  76. glEnd()
  77. of LINE:
  78. glBegin(GL_LINES)
  79. glColor4f(cmd.color.r, cmd.color.g, cmd.color.b, cmd.color.a)
  80. glVertex2f(canvas.calculateX(x + cmd.x1, x), canvas.calculateY(y - cmd.y1, y))
  81. glVertex2f(canvas.calculateX(x + cmd.x2, x), canvas.calculateY(y - cmd.y2, y))
  82. glEnd()
  83. of RECT:
  84. glColor4f(cmd.color.r, cmd.color.g, cmd.color.b, cmd.color.a)
  85. glRectf(
  86. canvas.calculateX(x + cmd.x1, x), canvas.calculateY(y - cmd.y1, y),
  87. canvas.calculateX(x + cmd.x2, x), canvas.calculateY(y - cmd.y2, y))
  88. of FILL:
  89. glColor4f(cmd.color.r, cmd.color.g, cmd.color.b, cmd.color.a)
  90. glRectf(x, y, x + canvas.rect_size.x, y - canvas.rect_size.y)
  91. of CIRCLE:
  92. glColor4f(cmd.color.r, cmd.color.g, cmd.color.b, cmd.color.a)
  93. glBegin(GL_TRIANGLE_FAN)
  94. glVertex2f(canvas.calculateX(x + cmd.x1, x), canvas.calculateY(y - cmd.y1, y))
  95. for i in countup(0, cmd.points.len()-1, 2):
  96. glVertex2f(
  97. canvas.calculateX(x + cmd.points[i] + cmd.x1, x),
  98. canvas.calculateY(y - cmd.y1 - cmd.points[i+1], y))
  99. glEnd()
  100. method duplicate*(self: CanvasPtr, obj: var CanvasObj): CanvasPtr {.base.} =
  101. ## Duplicates Canvas object and create a new Canvas pointer.
  102. obj = self[]
  103. obj.addr
  104. method circle*(canvas: CanvasPtr, x, y, radius: GLfloat, color: ColorRef, quality: int = 100) {.base.} =
  105. ## Draws a circle in the canvas.
  106. ##
  107. ## Arguments:
  108. ## - `x` - circle center at X axis.
  109. ## - `y` - circle center at Y axis.
  110. ## - `radius` - circle radius.
  111. ## - `color` - Color object.
  112. ## - `quality` - circle quality.
  113. var pnts: seq[GLfloat]
  114. for i in 0..quality:
  115. let angle = PI2*i.float/quality.float
  116. pnts.add(radius*cos(angle))
  117. pnts.add(radius*sin(angle))
  118. canvas.commands.add(DrawCommand(kind: CIRCLE, x1: x, y1: y, color: color, points: pnts))
  119. method point*(canvas: CanvasPtr, x, y: GLfloat, color: ColorRef) {.base.} =
  120. ## Draws a point in the canvas.
  121. ##
  122. ## Arguments:
  123. ## - `x` - point position at X axis.
  124. ## - `y` - point position at Y axis.
  125. ## - `color` - point color.
  126. canvas.commands.add(DrawCommand(kind: POINT, x1: x, y1: y, color: color))
  127. method line*(canvas: CanvasPtr, x1, y1, x2, y2: GLfloat, color: ColorRef) {.base.} =
  128. ## Draws a line in the canvas.
  129. ##
  130. ## Arguments:
  131. ## - `x1` - first position at X axis.
  132. ## - `y1` - first position at Y axis.
  133. ## - `x2` - second position at X axis.
  134. ## - `y2` - second position at Y axis.
  135. ## - `color` - line color.
  136. canvas.commands.add(DrawCommand(kind: LINE, x1: x1, y1: y1, x2: x2, y2: y2, color: color))
  137. method rect*(canvas: CanvasPtr, x1, y1, x2, y2: GLfloat, color: ColorRef) {.base.} =
  138. ## Draws a line in the canvas.
  139. ##
  140. ## Arguments:
  141. ## - `x1` - first position at X axis.
  142. ## - `y1` - first position at Y axis.
  143. ## - `x2` - second position at X axis.
  144. ## - `y2` - second position at Y axis.
  145. ## - `color` - rectangle color.
  146. canvas.commands.add(
  147. DrawCommand(kind: RECT, x1: x1, y1: y1, x2: x2, y2: y2, color: color)
  148. )
  149. method fill*(canvas: CanvasPtr, color: ColorRef) {.base.} =
  150. ## Fills canvas.
  151. canvas.commands = @[DrawCommand(kind: FILL, x1: 0, y1: 0, color: color)]
  152. method resize*(canvas: CanvasPtr, w, h: GLfloat) {.base.} =
  153. ## Resizes canvas.
  154. ##
  155. ## Arguments:
  156. ## - `w` is a new width.
  157. ## - `h` is a new height.
  158. canvas.rect_size.x = w
  159. canvas.rect_size.y = h
  160. canvas.can_use_anchor = false
  161. canvas.can_use_size_anchor = false