diff --git a/src/nodesnim/graphics/drawable.nim b/src/nodesnim/graphics/drawable.nim index ec0ad63f..a2329173 100644 --- a/src/nodesnim/graphics/drawable.nim +++ b/src/nodesnim/graphics/drawable.nim @@ -8,6 +8,8 @@ import ../core/vector2, ../core/tools, + ../private/templates, + strutils, re @@ -27,145 +29,12 @@ type DrawableRef* = ref DrawableObj -let standard_shadow_color: ColorRef = Color(0f, 0f, 0f, 0.5f) - -template drawablepattern*(`type`: untyped): untyped = - result = `type`( - texture: GlTextureObj(), border_width: 0, - border_detail: [8, 8, 8, 8], - border_radius: [0.float, 0, 0, 0], - border_color: Color(0, 0, 0, 0), - background_color: Color(0, 0, 0, 0), - shadow_offset: Vector2(0, 0), shadow: false, - shadow_color: standard_shadow_color - ) +let standard_shadow_color*: ColorRef = Color(0f, 0f, 0f, 0.5f) proc Drawable*: DrawableRef = drawablepattern(DrawableRef) -template vd* = - ## void template - discard - -template recalc*(shadow: bool = false) = - ## Calculates vertex positions. - let (xw, yh) = (x + width, y - height) - when not shadow: - # left top - for i in bezier_iter(1f/self.border_detail[0].float, Vector2(0, -self.border_radius[0]), - Vector2(0, 0), Vector2(self.border_radius[0], 0)): - vertex.add(Vector2(x + i.x, y + i.y)) - - # right top - for i in bezier_iter(1f/self.border_detail[1].float, Vector2(-self.border_radius[01], 0), - Vector2(0, 0), Vector2(0, -self.border_radius[1])): - vertex.add(Vector2(xw + i.x, y + i.y)) - - # right bottom - for i in bezier_iter(1f/self.border_detail[2].float, Vector2(0, -self.border_radius[2]), - Vector2(0, 0), Vector2(-self.border_radius[2], 0)): - vertex.add(Vector2(xw + i.x, yh - i.y)) - - # left bottom - for i in bezier_iter(1f/self.border_detail[3].float, Vector2(self.border_radius[3], 0), - Vector2(0, 0), Vector2(0, self.border_radius[3])): - vertex.add(Vector2(x + i.x, yh + i.y)) - else: - glBegin(GL_QUAD_STRIP) - # left top - for i in bezier_iter(1f/self.border_detail[0].float, Vector2(0, -self.border_radius[0]), - Vector2(0, 0), Vector2(self.border_radius[0], 0)): - glColor4f(0, 0, 0, 0) - glVertex2f(x + i.x + self.shadow_offset.x, y + i.y - self.shadow_offset.y) - glColor(self.shadow_color) - glVertex2f(x + i.x, y + i.y) - - # right top - for i in bezier_iter(1f/self.border_detail[1].float, Vector2(-self.border_radius[1], 0), - Vector2(0, 0), Vector2(0, -self.border_radius[1])): - glColor4f(0, 0, 0, 0) - glVertex2f(xw + i.x + self.shadow_offset.x, y + i.y - self.shadow_offset.y) - glColor(self.shadow_color) - glVertex2f(xw + i.x, y + i.y) - - # right bottom - for i in bezier_iter(1f/self.border_detail[2].float, Vector2(0, -self.border_radius[2]), - Vector2(0, 0), Vector2(-self.border_radius[2], 0)): - glColor4f(0, 0, 0, 0) - glVertex2f(xw + i.x + self.shadow_offset.x, yh - i.y - self.shadow_offset.y) - glColor(self.shadow_color) - glVertex2f(xw + i.x, yh - i.y) - - # left bottom - for i in bezier_iter(1f/self.border_detail[3].float, Vector2(self.border_radius[3], 0), - Vector2(0, 0), Vector2(0, self.border_radius[3])): - glColor4f(0, 0, 0, 0) - glVertex2f(x + i.x + self.shadow_offset.x, yh + i.y - self.shadow_offset.y) - glColor(self.shadow_color) - glVertex2f(x + i.x, yh + i.y) - - glColor4f(0, 0, 0, 0) - glVertex2f(x + self.shadow_offset.x, y - self.border_radius[0] - self.shadow_offset.y) - glColor(self.shadow_color) - glVertex2f(x, y - self.border_radius[0]) - glEnd() - - -template draw_template*(drawtype, color, function, secondfunc: untyped): untyped = - ## Draws colorized vertexes - ## - ## Arguments: - ## - `drawtype` - draw type, like `GL_POLYGON` - ## - `color` - color for border drawing. - ## - `function` - function called before `glBegin` - ## - `secondfunc` - function called after `glEnd` - glColor4f(`color`.r, `color`.g, `color`.b, `color`.a) - `function` - glBegin(`drawtype`) - - for i in vertex: - glVertex2f(i.x, i.y) - - glEnd() - `secondfunc` - -template draw_texture_template*(drawtype, color, function, secondfunc: untyped): untyped = - glEnable(GL_TEXTURE_2D) - glBindTexture(GL_TEXTURE_2D, self.texture.texture) - glColor4f(`color`.r, `color`.g, `color`.b, `color`.a) - `function` - glBegin(`drawtype`) - var - texture_size = self.texture.size - h = height - w = width - if texture_size.x < width: - let q = width / texture_size.x - texture_size.x *= q - texture_size.y *= q - - if texture_size.y < height: - let q = height / texture_size.y - texture_size.x *= q - texture_size.y *= q - - # crop .. :eyes: - let q = width / texture_size.x - texture_size.x *= q - texture_size.y *= q - h /= height/width - - for i in vertex: - glTexCoord2f((-x + i.x - w + texture_size.x) / texture_size.x, - (y - i.y - h + texture_size.y) / texture_size.y) - glVertex2f(i.x, i.y) - - glEnd() - `secondfunc` - glDisable(GL_TEXTURE_2D) - - method enableShadow*(self: DrawableRef, val: bool = true) {.base.} = ## Enables shadow, when `val` is true. self.shadow = val @@ -177,15 +46,15 @@ method draw*(self: DrawableRef, x1, y1, width, height: float) {.base.} = y = y1 if self.shadow: - recalc(true) - recalc() + calculateDrawableCorners(true) + calculateDrawableCorners() if self.texture.texture > 0'u32: - draw_texture_template(GL_POLYGON, self.background_color, vd(), vd()) + drawTextureTemplate(GL_POLYGON, self.background_color, voidTemplate(), voidTemplate()) else: - draw_template(GL_POLYGON, self.background_color, vd(), vd()) + drawTemplate(GL_POLYGON, self.background_color, voidTemplate(), voidTemplate()) if self.border_width > 0f: - draw_template(GL_LINE_LOOP, self.border_color, glLineWidth(self.border_width), glLineWidth(1)) + drawTemplate(GL_LINE_LOOP, self.border_color, glLineWidth(self.border_width), glLineWidth(1)) method getColor*(self: DrawableRef): ColorRef {.base.} = diff --git a/src/nodesnim/graphics/gradient_drawable.nim b/src/nodesnim/graphics/gradient_drawable.nim index b7ccaa47..a6aa5bfc 100644 --- a/src/nodesnim/graphics/gradient_drawable.nim +++ b/src/nodesnim/graphics/gradient_drawable.nim @@ -6,6 +6,9 @@ import ../core/stylesheet, ../core/image, ../core/vector2, + ../core/tools, + + ../private/templates, drawable, strutils @@ -23,39 +26,6 @@ proc GradientDrawable*: GradientDrawableRef = Color(1f, 1f, 1f, 1.0), Color(1f, 1f, 1f, 1.0)] - -template draw_template*(drawtype, color, function, secondfunc: untyped, is_gradient: bool = true): untyped = - ## Draws colorized vertexes - ## - ## Arguments: - ## - `drawtype` - draw type, like `GL_POLYGON` - ## - `color` - color for border drawing. - ## - `function` - function called before `glBegin` - ## - `secondfunc` - function called after `glEnd` - ## - `is_gradient` - true when drawtype is `GL_POLYGON`. - glColor4f(`color`.r, `color`.g, `color`.b, `color`.a) - `function` - glBegin(`drawtype`) - - if is_gradient: - for i in 0..vertex.high: - let tmp = i/vertex.len() - if tmp < 0.25: - glColor(self.corners[0]) - elif tmp < 0.5: - glColor(self.corners[1]) - elif tmp < 0.75: - glColor(self.corners[2]) - else: - glColor(self.corners[3]) - glVertex2f(vertex[i].x, vertex[i].y) - else: - for i in vertex: - glVertex2f(i.x, i.y) - - glEnd() - `secondfunc` - method draw*(self: GradientDrawableRef, x1, y1, width, height: float) = var vertex: seq[Vector2Obj] = @[] @@ -63,16 +33,15 @@ method draw*(self: GradientDrawableRef, x1, y1, width, height: float) = y = y1 if self.shadow: - recalc(true) - - recalc() + calculateDrawableCorners(true) + calculateDrawableCorners() if self.texture.texture > 0'u32: - draw_texture_template(GL_POLYGON, self.background_color, vd(), vd()) + drawTextureTemplate(GL_POLYGON, self.background_color, voidTemplate(), voidTemplate()) else: - draw_template(GL_POLYGON, self.background_color, vd(), vd()) + drawTemplate(GL_POLYGON, self.background_color, voidTemplate(), voidTemplate(), true) if self.border_width > 0f: - draw_template(GL_LINE_LOOP, self.border_color, glLineWidth(self.border_width), glLineWidth(1), false) + drawTemplate(GL_LINE_LOOP, self.border_color, glLineWidth(self.border_width), glLineWidth(1), false) method setCornerColors*(self: GradientDrawableRef, c0, c1, c2, c3: ColorRef) {.base.} = ## Changes corners colors diff --git a/src/nodesnim/nodes/animation_player.nim b/src/nodesnim/nodes/animation_player.nim index 12d65220..0d40b1af 100644 --- a/src/nodesnim/nodes/animation_player.nim +++ b/src/nodesnim/nodes/animation_player.nim @@ -1,10 +1,11 @@ # author: Ethosa ## Provides animation in most nodes import - node, + ../thirdparty/opengl, ../core/enums, ../core/tools, - ../thirdparty/opengl + ../private/templates, + node type diff --git a/src/nodesnim/nodes/audio_stream_player.nim b/src/nodesnim/nodes/audio_stream_player.nim index 81754137..73d41de8 100644 --- a/src/nodesnim/nodes/audio_stream_player.nim +++ b/src/nodesnim/nodes/audio_stream_player.nim @@ -3,10 +3,11 @@ ## ## AudioStream is responsible for audio. You can play multiple audio recordings at once. import - node, ../thirdparty/sdl2/mixer, ../core/enums, - ../core/audio_stream + ../core/audio_stream, + ../private/templates, + node type diff --git a/src/nodesnim/nodes/canvas.nim b/src/nodesnim/nodes/canvas.nim index 370478a0..802ea5b8 100644 --- a/src/nodesnim/nodes/canvas.nim +++ b/src/nodesnim/nodes/canvas.nim @@ -4,18 +4,17 @@ ## Canvas used for drawing primitive geometry. import ../thirdparty/sdl2 except Color import - math, ../thirdparty/opengl, ../thirdparty/sdl2/image, - ../core/vector2, ../core/color, ../core/anchor, ../core/enums, ../core/font, ../core/tools, - - node + ../private/templates, + node, + math const TAU = PI + PI @@ -59,24 +58,6 @@ proc Canvas*(name: string = "Canvas"): CanvasRef = result.type_of_node = NODE_TYPE_CONTROL -# --- Private --- # -template loadColor(color_argument_name: untyped): untyped = - let clr = toUint32Tuple(`color_argument_name`) - canvas.renderer.setDrawColor(clr.r.uint8, clr.g.uint8, clr.b.uint8, clr.a.uint8) - -template loadGL(canvas: untyped): untyped = - if `canvas`.canvas_texture == 0: - glGenTextures(1, `canvas`.canvas_texture.addr) - glBindTexture(GL_TEXTURE_2D, `canvas`.canvas_texture) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA.GLint, `canvas`.surface.w, `canvas`.surface.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, `canvas`.surface.pixels) - glBindTexture(GL_TEXTURE_2D, 0) - - -# --- Public --- # method calcGlobalPosition*(self: CanvasRef) {.base.} = ## Returns global node position. self.global_position = self.position @@ -184,7 +165,7 @@ method resize*(self: CanvasRef, w, h: GLfloat, save_anchor: bool = false) {.base self.surface.freeSurface() self.surface = new_surface self.renderer = self.surface.createSoftwareRenderer() - loadGL(self) + canvasDrawGL(self) method setAnchor*(self: CanvasRef, anchor: AnchorObj) {.base.} = ## Changes node anchor. @@ -222,10 +203,10 @@ proc bezier*(canvas: CanvasRef, x1, y1, x2, y2, x3, y3: GLfloat, color: ColorRef ## ## See also: ## - `cubicBezier proc <#cubicBezier,CanvasRef,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,ColorRef>`_ - loadColor(color) + colorToRenderer(color) for pnt in bezier_iter(0.001, Vector2(x1, y1), Vector2(x2, y2), Vector2(x3, y3)): canvas.renderer.drawPoint(pnt.x.cint, pnt.y.cint) - loadGL(canvas) + canvasDrawGL(canvas) proc circle*(canvas: CanvasRef, x, y, radius: GLfloat, color: ColorRef, quality: int = 100) = ## Draws a circle in the canvas. @@ -236,11 +217,11 @@ proc circle*(canvas: CanvasRef, x, y, radius: GLfloat, color: ColorRef, quality: ## - `radius` - circle radius. ## - `color` - Color object. ## - `quality` - circle quality. - loadColor(color) + colorToRenderer(color) for i in 0..quality: let angle = TAU*i.float/quality.float canvas.renderer.drawPoint((x + radius*cos(angle)).cint, (y + radius*sin(angle)).cint) - loadGL(canvas) + canvasDrawGL(canvas) proc cubicBezier*(canvas: CanvasRef, x1, y1, x2, y2, x3, y3, x4, y4: GLfloat, color: ColorRef) = ## Draws a quadric bezier curve at 4 points. @@ -253,16 +234,16 @@ proc cubicBezier*(canvas: CanvasRef, x1, y1, x2, y2, x3, y3, x4, y4: GLfloat, co ## ## See also: ## - `bezier proc <#bezier,CanvasRef,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,GLfloat,ColorRef>`_ - loadColor(color) + colorToRenderer(color) for pnt in cubic_bezier_iter(0.001, Vector2(x1, y1), Vector2(x2, y2), Vector2(x3, y3), Vector2(x4, y4)): canvas.renderer.drawPoint(pnt.x.cint, pnt.y.cint) - loadGL(canvas) + canvasDrawGL(canvas) proc fill*(canvas: CanvasRef, color: ColorRef) = ## Fills canvas. - loadColor(color) + colorToRenderer(color) canvas.renderer.clear() - loadGL(canvas) + canvasDrawGL(canvas) proc line*(canvas: CanvasRef, x1, y1, x2, y2: GLfloat, color: ColorRef) = ## Draws a line in the canvas. @@ -273,9 +254,9 @@ proc line*(canvas: CanvasRef, x1, y1, x2, y2: GLfloat, color: ColorRef) = ## - `x2` - second position at X axis. ## - `y2` - second position at Y axis. ## - `color` - line color. - loadColor(color) + colorToRenderer(color) canvas.renderer.drawLine(x1.cint, y1.cint, x2.cint, y2.cint) - loadGL(canvas) + canvasDrawGL(canvas) proc rect*(canvas: CanvasRef, x1, y1, x2, y2: GLfloat, color: ColorRef) = ## Draws a line in the canvas. @@ -286,10 +267,10 @@ proc rect*(canvas: CanvasRef, x1, y1, x2, y2: GLfloat, color: ColorRef) = ## - `x2` - second position at X axis. ## - `y2` - second position at Y axis. ## - `color` - rectangle color. - loadColor(color) + colorToRenderer(color) var rectangle = rect(x1.cint, y1.cint, x2.cint, y2.cint) canvas.renderer.drawRect(rectangle) - loadGL(canvas) + canvasDrawGL(canvas) proc fillRect*(canvas: CanvasRef, x1, y1, x2, y2: GLfloat, color: ColorRef) = ## Draws a line in the canvas. @@ -300,10 +281,10 @@ proc fillRect*(canvas: CanvasRef, x1, y1, x2, y2: GLfloat, color: ColorRef) = ## - `x2` - second position at X axis. ## - `y2` - second position at Y axis. ## - `color` - rectangle color. - loadColor(color) + colorToRenderer(color) var rectangle = rect(x1.cint, y1.cint, x2.cint, y2.cint) canvas.renderer.fillRect(rectangle) - loadGL(canvas) + canvasDrawGL(canvas) proc point*(canvas: CanvasRef, x, y: GLfloat, color: ColorRef) = ## Draws a point in the canvas. @@ -312,9 +293,9 @@ proc point*(canvas: CanvasRef, x, y: GLfloat, color: ColorRef) = ## - `x` - point position at X axis. ## - `y` - point position at Y axis. ## - `color` - point color. - loadColor(color) + colorToRenderer(color) canvas.renderer.drawPoint(x.cint, y.cint) - loadGL(canvas) + canvasDrawGL(canvas) proc text*(canvas: CanvasRef, text: StyleText | string, x, y: Glfloat, align: Vector2Obj = Vector2()) = ## Draws multiline text. @@ -331,7 +312,7 @@ proc text*(canvas: CanvasRef, text: StyleText | string, x, y: Glfloat, align: Ve surface = stext(text).renderSurface(Anchor(align.x, 0, align.y, 0)) rectangle = rect(x.cint, y.cint, x.cint+surface.w, y.cint+surface.h) surface.blitSurface(nil, canvas.surface, rectangle.addr) - loadGL(canvas) + canvasDrawGL(canvas) proc saveAs*(self: CanvasRef, filename: cstring) = ## Saves canvas as image file. diff --git a/src/nodesnim/nodes/node.nim b/src/nodesnim/nodes/node.nim index 469aaa09..515e7c4b 100644 --- a/src/nodesnim/nodes/node.nim +++ b/src/nodesnim/nodes/node.nim @@ -8,7 +8,9 @@ import ../core/vector2, ../core/enums, ../core/anchor, - ../core/input + ../core/input, + + ../private/templates {.used.} @@ -37,21 +39,6 @@ let handler_default* = proc(self: NodeRef) = discard event_handler_default* = proc(self: NodeRef, event: InputEvent) = discard - -template nodepattern*(nodetype: untyped): untyped = - ## This used in childs of the NodeObj. - result = `nodetype`( - name: name, children: @[], - on_ready: handler_default, - on_process: handler_default, - on_input: event_handler_default, - on_enter: handler_default, - on_exit: handler_default, - on_theme_changed: handler_default, - is_ready: false, pausemode: INHERIT, visibility: VISIBLE - ) - result.type_of_node = NODE_TYPE_DEFAULT - proc Node*(name: string = "Node"): NodeRef = ## Creates a new Node. nodepattern(NodeRef) diff --git a/src/nodesnim/nodes/scene.nim b/src/nodesnim/nodes/scene.nim index d7d8a835..c2f7a710 100644 --- a/src/nodesnim/nodes/scene.nim +++ b/src/nodesnim/nodes/scene.nim @@ -1,8 +1,6 @@ # author: Ethosa ## The Scene uses in the `window.nim`. It contains other nodes. Only one scene can work at a time. import - node, - canvas, ../thirdparty/opengl, ../thirdparty/opengl/glu, ../core/enums, @@ -10,8 +8,11 @@ import ../core/vector2, ../core/vector3, ../core/themes, + ../private/templates, ../nodes3d/node3d, - ../nodes3d/camera3d + ../nodes3d/camera3d, + node, + canvas type diff --git a/src/nodesnim/nodes2d/animated_sprite.nim b/src/nodesnim/nodes2d/animated_sprite.nim index 14e570ad..aaa23a91 100644 --- a/src/nodesnim/nodes2d/animated_sprite.nim +++ b/src/nodesnim/nodes2d/animated_sprite.nim @@ -11,6 +11,7 @@ import ../core/image, ../core/color, ../core/animation, + ../private/templates, ../nodes/node, node2d diff --git a/src/nodesnim/nodes2d/camera2d.nim b/src/nodesnim/nodes2d/camera2d.nim index 2f9c3e45..4babb56b 100644 --- a/src/nodesnim/nodes2d/camera2d.nim +++ b/src/nodesnim/nodes2d/camera2d.nim @@ -7,6 +7,7 @@ import ../core/anchor, ../core/input, ../core/enums, + ../private/templates, ../nodes/node, ../nodes/canvas, diff --git a/src/nodesnim/nodes2d/collision_shape2d.nim b/src/nodesnim/nodes2d/collision_shape2d.nim index 182a534b..b18468e2 100644 --- a/src/nodesnim/nodes2d/collision_shape2d.nim +++ b/src/nodesnim/nodes2d/collision_shape2d.nim @@ -8,6 +8,7 @@ import ../core/enums, ../core/circle, ../core/polygon2, + ../private/templates, ../nodes/node, ../nodes/canvas, diff --git a/src/nodesnim/nodes2d/kinematic_body2d.nim b/src/nodesnim/nodes2d/kinematic_body2d.nim index 161185ea..298c27eb 100644 --- a/src/nodesnim/nodes2d/kinematic_body2d.nim +++ b/src/nodesnim/nodes2d/kinematic_body2d.nim @@ -9,6 +9,7 @@ import ../core/anchor, ../core/input, ../core/enums, + ../private/templates, ../nodes/node, ../nodes/canvas, diff --git a/src/nodesnim/nodes2d/node2d.nim b/src/nodesnim/nodes2d/node2d.nim index 5e2d9c80..bfde2dfc 100644 --- a/src/nodesnim/nodes2d/node2d.nim +++ b/src/nodesnim/nodes2d/node2d.nim @@ -8,6 +8,7 @@ import ../core/anchor, ../core/input, ../core/enums, + ../private/templates, ../nodes/node, ../nodes/canvas @@ -24,20 +25,6 @@ type Node2DRef* = ref Node2DObj -template node2dpattern*: untyped = - result.centered = false - result.timed_position = Vector2() - result.rect_size = Vector2() - result.rect_min_size = Vector2() - result.position = Vector2() - result.global_position = Vector2() - result.anchor = Anchor(0, 0, 0, 0) - result.size_anchor = Vector2() - result.z_index = 0f - result.z_index_global = 0f - result.relative_z_index = true - result.type_of_node = NODE_TYPE_2D - proc Node2D*(name: string = "Node2D"): Node2DRef = ## Creates a new Node2D. ## diff --git a/src/nodesnim/nodes2d/sprite.nim b/src/nodesnim/nodes2d/sprite.nim index 2374270d..b1c64dfc 100644 --- a/src/nodesnim/nodes2d/sprite.nim +++ b/src/nodesnim/nodes2d/sprite.nim @@ -10,6 +10,7 @@ import ../core/enums, ../core/image, ../core/color, + ../private/templates, ../nodes/node, ../nodes/canvas, diff --git a/src/nodesnim/nodes2d/tilemap.nim b/src/nodesnim/nodes2d/tilemap.nim index 68da7539..964a5169 100644 --- a/src/nodesnim/nodes2d/tilemap.nim +++ b/src/nodesnim/nodes2d/tilemap.nim @@ -6,6 +6,8 @@ import ../core/enums, ../core/input, ../core/tileset, + ../core/anchor, + ../private/templates, ../nodes/node, node2d diff --git a/src/nodesnim/nodes2d/ysort.nim b/src/nodesnim/nodes2d/ysort.nim index ce9d0f39..0a2a9118 100644 --- a/src/nodesnim/nodes2d/ysort.nim +++ b/src/nodesnim/nodes2d/ysort.nim @@ -8,6 +8,7 @@ import ../core/anchor, ../core/input, ../core/enums, + ../private/templates, ../nodes/node, ../nodes/canvas, diff --git a/src/nodesnim/nodes3d/camera3d.nim b/src/nodesnim/nodes3d/camera3d.nim index 52ca6f72..1bb8059c 100644 --- a/src/nodesnim/nodes3d/camera3d.nim +++ b/src/nodesnim/nodes3d/camera3d.nim @@ -5,6 +5,7 @@ import ../core/vector3, ../core/input, ../core/enums, + ../private/templates, ../nodes/node, node3d, diff --git a/src/nodesnim/nodes3d/geometry_instance.nim b/src/nodesnim/nodes3d/geometry_instance.nim index 333be4cf..c3b1f21b 100644 --- a/src/nodesnim/nodes3d/geometry_instance.nim +++ b/src/nodesnim/nodes3d/geometry_instance.nim @@ -8,6 +8,7 @@ import ../core/anchor, ../core/input, ../core/color, + ../private/templates, ../nodes/node, node3d, diff --git a/src/nodesnim/nodes3d/node3d.nim b/src/nodesnim/nodes3d/node3d.nim index 2f1c0008..3a5d4813 100644 --- a/src/nodesnim/nodes3d/node3d.nim +++ b/src/nodesnim/nodes3d/node3d.nim @@ -5,6 +5,7 @@ import ../core/enums, ../core/anchor, ../core/input, + ../private/templates, ../nodes/node @@ -16,16 +17,6 @@ type Node3DRef* = ref Node3DObj -template node3dpattern* = - result.rotation = Vector3() - result.translation = Vector3() - result.scale = Vector3(1, 1, 1) - result.global_rotation = Vector3() - result.global_translation = Vector3() - result.global_scale = Vector3(1, 1, 1) - result.type_of_node = NODE_TYPE_3D - - proc Node3D*(name: string = "Node3D"): Node3DRef = ## Creates a new Node3D object. ## diff --git a/src/nodesnim/nodes3d/sprite3d.nim b/src/nodesnim/nodes3d/sprite3d.nim index 630becf5..433a24bc 100644 --- a/src/nodesnim/nodes3d/sprite3d.nim +++ b/src/nodesnim/nodes3d/sprite3d.nim @@ -9,6 +9,7 @@ import ../core/enums, ../core/image, ../core/color, + ../private/templates, ../nodes/node, node3d diff --git a/src/nodesnim/nodescontrol/box.nim b/src/nodesnim/nodescontrol/box.nim index c74a987d..ddf4fe17 100644 --- a/src/nodesnim/nodescontrol/box.nim +++ b/src/nodesnim/nodescontrol/box.nim @@ -8,6 +8,8 @@ import ../core/anchor, ../core/input, ../core/enums, + ../private/templates, + ../graphics/drawable, ../nodes/node, ../nodes/canvas, diff --git a/src/nodesnim/nodescontrol/button.nim b/src/nodesnim/nodescontrol/button.nim index 7b526490..d2774200 100644 --- a/src/nodesnim/nodescontrol/button.nim +++ b/src/nodesnim/nodescontrol/button.nim @@ -12,6 +12,7 @@ import ../core/color, ../core/font, ../core/themes, + ../private/templates, ../nodes/node, ../graphics/drawable, diff --git a/src/nodesnim/nodescontrol/chart.nim b/src/nodesnim/nodescontrol/chart.nim index a4dc5ef0..0104ffbb 100644 --- a/src/nodesnim/nodescontrol/chart.nim +++ b/src/nodesnim/nodescontrol/chart.nim @@ -10,6 +10,8 @@ import ../core/chartdata, ../core/themes, ../core/font, + ../private/templates, + ../graphics/drawable, ../nodes/node, @@ -42,137 +44,6 @@ method hasAxis*(self: ChartRef): bool {.base.} = false -template drawAxis(self: untyped) = - glColor(`self`.line_color) - glLineWidth(2) - glBegin(GL_LINE_STRIP) - glVertex2f(start_x, y) - glVertex2f(start_x, end_y) - glVertex2f(x + `self`.rect_size.x - `self`.rect_size.x/10, end_y) - glEnd() - - -template drawRadar = - let - value_step = max_val / 5 - radius_max = min(self.rect_size.x, self.rect_size.y)/2 - radius_step = radius_max/5 - center = Vector2(x + self.rect_size.x/2, y - self.rect_size.y/2) - angle_step = TAU / data.len.float - var - radius = radius_step - angle = 0f - val = value_step - glColor(current_theme~foreground) - glLineWidth(1) - for step in 0..5: - glBegin(GL_LINE_LOOP) - for i in data.low..data.high: - glVertex2f(center.x + cos(angle)*radius, center.y + sin(angle)*radius) - angle += angle_step - radius += radius_step - angle = 0f - glEnd() - - glBegin(GL_LINES) - for i in data.low..data.high: - glVertex2f(center.x + cos(angle)*radius_max, center.y + sin(angle)*radius_max) - glVertex2f(center.x, center.y) - angle += angle_step - angle = 0f - glEnd() - - glColor4f(chart_data.data_color.r, chart_data.data_color.g, chart_data.data_color.b, 0.8) - glBegin(GL_POLYGON) - for i in data.low..data.high: - let r = radius_max * (data[i][1].getNum() / max_val) - glVertex2f(center.x + cos(angle)*r, center.y + sin(angle)*r) - angle += angle_step - glEnd() - - angle = 0f - for i in data.low..data.high: - let - text = stext($data[i][0]) - size = text.getTextSize() - text.renderTo( - Vector2(center.x + cos(angle)*(radius_max+radius_step) - size.x/2, - center.y + sin(angle)*(radius_max+radius_step) + size.y), - size, Anchor()) - angle += angle_step - text.freeMemory() - - radius = radius_step - for step in 0..5: - let - text = stext($val, current_theme~foreground) - size = text.getTextSize() - text.setBold(true) - text.renderTo(Vector2(center.x - size.x, center.y + radius+radius_step/2), size, Anchor()) - radius += radius_step - val += value_step - text.freeMemory() - - -template drawLine = - glBegin(GL_LINE_STRIP) - for i in data.low..data.high: - let - j = i.float - h = max_height * (data[i][1].getNum() / max_val) - glVertex2f(start_x + section_width*j + section_width/2, end_y + h) - glEnd() - - -template drawBar = - let - height_step = max_height / 5 - value_step = max_val / 5 - var - height = height_step - value = value_step - for i in data.low..data.high: - let - j = i.float - h = max_height * (data[i][1].getNum() / max_val) - glColor(chart_data.data_color) - glRectf(start_x + section_width*j, end_y + h, start_x + section_width*(j+1), end_y) - - let - text = stext($data[i][0]) - value_text = stext($value) - size = text.getTextSize() - value_size = value_text.getTextSize() - text.renderTo(Vector2(start_x+section_width*j, end_y), size, Anchor()) - value_text.renderTo(Vector2(start_x - value_size.x - 2, end_y + height), size, Anchor()) - height += height_step - value += value_step - text.freeMemory() - value_text.freeMemory() - - -template drawPie(chart_data: untyped) = - let - d = `chart_data`.getSorted() - sum = `chart_data`.getSum() - radius = min(self.rect_size.x, self.rect_size.y)/2 - center = Vector2(x + self.rect_size.x/2, y - self.rect_size.y/2) - var - angle = PI/2 - a: float - for i in d.low..d.high: - glBegin(GL_TRIANGLE_FAN) - glVertex2f(center.x, center.y) - a = angle - angle += d[i][1].getNum() / sum * TAU - while a <= angle: - glVertex2f(center.x + cos(a)*radius, center.y + sin(a)*radius) - a += 0.01 - glEnd() - glColor4f(angle/6, angle/5, angle/4, 1f) - - - method draw*(self: ChartRef, w, h: GLfloat) = {.warning[LockLevel]: off.} procCall self.ControlRef.draw(w, h) @@ -183,7 +54,7 @@ method draw*(self: ChartRef, w, h: GLfloat) = end_y = y - self.rect_size.y + self.rect_size.y/10 if self.hasAxis(): - self.drawAxis() + self.chartDrawAxis() for chart_data in self.data: let @@ -195,13 +66,13 @@ method draw*(self: ChartRef, w, h: GLfloat) = glColor(chart_data.data_color) case chart_data.chart_type of LINE_CHART: - drawLine() + chartDrawLine() of BAR_CHART: - drawBar() + chartDrawBar() of PIE_CHART: - chart_data.drawPie() + chart_data.chartDrawPie() of RADAR_CHART: - drawRadar() + chartDrawRadar() method addChartData*(self: ChartRef, chart_data: ChartData) {.base.} = diff --git a/src/nodesnim/nodescontrol/checkbox.nim b/src/nodesnim/nodescontrol/checkbox.nim index 35a2d1d6..4410d46a 100644 --- a/src/nodesnim/nodescontrol/checkbox.nim +++ b/src/nodesnim/nodescontrol/checkbox.nim @@ -10,6 +10,7 @@ import ../core/themes, ../core/anchor, ../core/nodes_os, + ../private/templates, ../graphics/drawable, diff --git a/src/nodesnim/nodescontrol/color_rect.nim b/src/nodesnim/nodescontrol/color_rect.nim index efb20a96..69ac3e54 100644 --- a/src/nodesnim/nodescontrol/color_rect.nim +++ b/src/nodesnim/nodescontrol/color_rect.nim @@ -9,6 +9,7 @@ import ../core/input, ../core/color, ../core/enums, + ../private/templates, ../nodes/node, ../graphics/drawable, diff --git a/src/nodesnim/nodescontrol/control.nim b/src/nodesnim/nodescontrol/control.nim index 093ffd61..b4c6e4dd 100644 --- a/src/nodesnim/nodescontrol/control.nim +++ b/src/nodesnim/nodescontrol/control.nim @@ -10,6 +10,7 @@ import ../core/enums, ../core/color, ../core/stylesheet, + ../private/templates, ../graphics/drawable, @@ -40,32 +41,9 @@ type on_unfocus*: ControlHandler ## This called when the Control node loses focus. ControlRef* = ref ControlObj -let control_handler = proc(self: ControlRef) = discard -let control_xy_handler = proc(self: ControlRef, x, y: float) = discard - -template controlpattern*: untyped = - result.hovered = false - result.focused = false - result.pressed = false - - result.mousemode = MOUSEMODE_SEE - result.rect_size = Vector2() - result.rect_min_size = Vector2() - result.position = Vector2() - result.global_position = Vector2() - result.size_anchor = Vector2() - result.anchor = Anchor(0, 0, 0, 0) - result.padding = Anchor(0, 0, 0, 0) - result.background = Drawable() - - result.on_mouse_enter = control_xy_handler - result.on_mouse_exit = control_xy_handler - result.on_click = control_xy_handler - result.on_press = control_xy_handler - result.on_release = control_xy_handler - result.on_focus = control_handler - result.on_unfocus = control_handler - result.type_of_node = NODE_TYPE_CONTROL +let + control_handler* = proc(self: ControlRef) = discard + control_xy_handler* = proc(self: ControlRef, x, y: float) = discard proc Control*(name: string = "Control"): ControlRef = ## Creates a new Control. diff --git a/src/nodesnim/nodescontrol/counter.nim b/src/nodesnim/nodescontrol/counter.nim index d852f82e..345c1902 100644 --- a/src/nodesnim/nodescontrol/counter.nim +++ b/src/nodesnim/nodescontrol/counter.nim @@ -12,6 +12,7 @@ import ../core/color, ../core/font, ../core/themes, + ../private/templates, ../nodes/node, ../nodes/canvas, @@ -70,6 +71,8 @@ method draw*(self: CounterRef, w, h: GLfloat) = self.background.draw(x, y, self.rect_size.x, self.rect_size.y) + if theme_changed: + self.label.text.rendered = false self.label.text.renderTo( Vector2(x + self.label.padding.x1, y - self.label.padding.y1), self.rect_size, self.label.text_align) diff --git a/src/nodesnim/nodescontrol/edittext.nim b/src/nodesnim/nodescontrol/edittext.nim index e2a2578c..d878f84c 100644 --- a/src/nodesnim/nodescontrol/edittext.nim +++ b/src/nodesnim/nodescontrol/edittext.nim @@ -13,9 +13,11 @@ import ../core/rect2, ../core/nodes_os, ../core/themes, + ../private/templates, ../nodes/node, ../nodes/canvas, + ../graphics/drawable, label, control @@ -124,23 +126,6 @@ method draw*(self: EditTextRef, w, h: Glfloat) = y1 += h.float inc i - -template changeText(self, `text`, `save_properties`, t: untyped): untyped = - var st = stext(`text`) - if `self`.`t`.font.isNil(): - `self`.`t`.font = standard_font - st.font = `self`.`t`.font - - if `save_properties`: - for i in 0.. 0: self.caret_pos[0] += value.uint32 @@ -169,10 +154,10 @@ method setText*(self: EditTextRef, t: string, save_properties: bool = false) = ## Arguments: ## - `text` is a new Label text. ## - `save_properties` - saves old text properties, if `true`. - changeText(self, t, save_properties, text) + setTextTemplate(self, t, save_properties, text) method setHint*(self: EditTextRef, t: string, save_properties: bool = false) {.base.} = - changeText(self, t, save_properties, hint) + setTextTemplate(self, t, save_properties, hint) method setHintColor*(self: EditTextRef, color: ColorRef) {.base.} = self.hint.setColor(color) diff --git a/src/nodesnim/nodescontrol/grid_box.nim b/src/nodesnim/nodescontrol/grid_box.nim index c83a1c3e..def0a8dd 100644 --- a/src/nodesnim/nodescontrol/grid_box.nim +++ b/src/nodesnim/nodescontrol/grid_box.nim @@ -8,9 +8,11 @@ import ../core/anchor, ../core/input, ../core/enums, + ../private/templates, ../nodes/node, ../nodes/canvas, + ../graphics/drawable, control, box diff --git a/src/nodesnim/nodescontrol/hbox.nim b/src/nodesnim/nodescontrol/hbox.nim index cb1bbfe0..bdd170b3 100644 --- a/src/nodesnim/nodescontrol/hbox.nim +++ b/src/nodesnim/nodescontrol/hbox.nim @@ -8,9 +8,11 @@ import ../core/anchor, ../core/input, ../core/enums, + ../private/templates, ../nodes/node, ../nodes/canvas, + ../graphics/drawable, control, box diff --git a/src/nodesnim/nodescontrol/label.nim b/src/nodesnim/nodescontrol/label.nim index 3984791a..86ae6510 100644 --- a/src/nodesnim/nodescontrol/label.nim +++ b/src/nodesnim/nodescontrol/label.nim @@ -15,6 +15,7 @@ import ../core/font, ../core/nodes_os, ../core/themes, + ../private/templates, ../graphics/drawable, diff --git a/src/nodesnim/nodescontrol/popup.nim b/src/nodesnim/nodescontrol/popup.nim index b95a8d07..1842953a 100644 --- a/src/nodesnim/nodescontrol/popup.nim +++ b/src/nodesnim/nodescontrol/popup.nim @@ -7,6 +7,7 @@ import ../core/input, ../core/enums, ../core/color, + ../private/templates, ../nodes/node, ../graphics/drawable, diff --git a/src/nodesnim/nodescontrol/progress_bar.nim b/src/nodesnim/nodescontrol/progress_bar.nim index 33527c6c..a6a48a18 100644 --- a/src/nodesnim/nodescontrol/progress_bar.nim +++ b/src/nodesnim/nodescontrol/progress_bar.nim @@ -11,6 +11,7 @@ import ../core/enums, ../core/nodes_os, ../core/themes, + ../private/templates, ../nodes/node, ../nodes/canvas, diff --git a/src/nodesnim/nodescontrol/scroll.nim b/src/nodesnim/nodescontrol/scroll.nim index 0ba272fb..fa55054d 100644 --- a/src/nodesnim/nodescontrol/scroll.nim +++ b/src/nodesnim/nodescontrol/scroll.nim @@ -11,6 +11,7 @@ import ../core/enums, ../core/color, ../core/themes, + ../private/templates, ../nodes/node, ../nodes/canvas, diff --git a/src/nodesnim/nodescontrol/slider.nim b/src/nodesnim/nodescontrol/slider.nim index bf0c6ecc..52df1bb1 100644 --- a/src/nodesnim/nodescontrol/slider.nim +++ b/src/nodesnim/nodescontrol/slider.nim @@ -10,6 +10,7 @@ import ../core/color, ../core/themes, ../core/enums, + ../private/templates, ../nodes/node, ../graphics/drawable, diff --git a/src/nodesnim/nodescontrol/subwindow.nim b/src/nodesnim/nodescontrol/subwindow.nim index 3b727f7a..fec79021 100644 --- a/src/nodesnim/nodescontrol/subwindow.nim +++ b/src/nodesnim/nodescontrol/subwindow.nim @@ -13,6 +13,7 @@ import ../core/image, ../core/font, ../core/themes, + ../private/templates, ../nodes/node, ../nodes/canvas, diff --git a/src/nodesnim/nodescontrol/switch.nim b/src/nodesnim/nodescontrol/switch.nim index 4e5ce6a3..7de9172c 100644 --- a/src/nodesnim/nodescontrol/switch.nim +++ b/src/nodesnim/nodescontrol/switch.nim @@ -10,8 +10,10 @@ import ../core/color, ../core/enums, ../core/themes, + ../private/templates, ../nodes/node, + ../graphics/drawable, control diff --git a/src/nodesnim/nodescontrol/texture_button.nim b/src/nodesnim/nodescontrol/texture_button.nim index 9f9cad90..6bc727db 100644 --- a/src/nodesnim/nodescontrol/texture_button.nim +++ b/src/nodesnim/nodescontrol/texture_button.nim @@ -12,8 +12,10 @@ import ../core/image, ../core/color, ../core/font, + ../private/templates, ../nodes/node, + ../graphics/drawable, control, label diff --git a/src/nodesnim/nodescontrol/texture_progress_bar.nim b/src/nodesnim/nodescontrol/texture_progress_bar.nim index a2ebda64..96ce480a 100644 --- a/src/nodesnim/nodescontrol/texture_progress_bar.nim +++ b/src/nodesnim/nodescontrol/texture_progress_bar.nim @@ -9,6 +9,7 @@ import ../core/input, ../core/image, ../core/enums, + ../private/templates, ../nodes/node, ../graphics/drawable, diff --git a/src/nodesnim/nodescontrol/texture_rect.nim b/src/nodesnim/nodescontrol/texture_rect.nim index 019c436a..b67e788f 100644 --- a/src/nodesnim/nodescontrol/texture_rect.nim +++ b/src/nodesnim/nodescontrol/texture_rect.nim @@ -10,6 +10,7 @@ import ../core/image, ../core/enums, ../core/color, + ../private/templates, ../nodes/node, ../graphics/drawable, diff --git a/src/nodesnim/nodescontrol/tooltip.nim b/src/nodesnim/nodescontrol/tooltip.nim index 398f026e..38fc857c 100644 --- a/src/nodesnim/nodescontrol/tooltip.nim +++ b/src/nodesnim/nodescontrol/tooltip.nim @@ -8,6 +8,7 @@ import ../core/color, ../core/anchor, ../core/themes, + ../private/templates, ../nodes/node, ../nodes/canvas, diff --git a/src/nodesnim/nodescontrol/vbox.nim b/src/nodesnim/nodescontrol/vbox.nim index 96f1d788..fe57492d 100644 --- a/src/nodesnim/nodescontrol/vbox.nim +++ b/src/nodesnim/nodescontrol/vbox.nim @@ -8,9 +8,11 @@ import ../core/anchor, ../core/input, ../core/enums, + ../private/templates, ../nodes/node, ../nodes/canvas, + ../graphics/drawable, control, box diff --git a/src/nodesnim/private.nim b/src/nodesnim/private.nim new file mode 100644 index 00000000..dfda980d --- /dev/null +++ b/src/nodesnim/private.nim @@ -0,0 +1,6 @@ +# author: Ethosa +import + private/templates + +export + templates diff --git a/src/nodesnim/private/templates.nim b/src/nodesnim/private/templates.nim new file mode 100644 index 00000000..afde6068 --- /dev/null +++ b/src/nodesnim/private/templates.nim @@ -0,0 +1,413 @@ +# author: Ethosa + + +template voidTemplate* = discard + + +# ----- Graphics templates ----- # + +template calculateDrawableCorners*(shadow: bool = false) = + ## Calculates vertex positions. + let (xw, yh) = (x + width, y - height) + when not shadow: + # left top + for i in bezier_iter(1f/self.border_detail[0].float, Vector2(0, -self.border_radius[0]), + Vector2(0, 0), Vector2(self.border_radius[0], 0)): + vertex.add(Vector2(x + i.x, y + i.y)) + + # right top + for i in bezier_iter(1f/self.border_detail[1].float, Vector2(-self.border_radius[01], 0), + Vector2(0, 0), Vector2(0, -self.border_radius[1])): + vertex.add(Vector2(xw + i.x, y + i.y)) + + # right bottom + for i in bezier_iter(1f/self.border_detail[2].float, Vector2(0, -self.border_radius[2]), + Vector2(0, 0), Vector2(-self.border_radius[2], 0)): + vertex.add(Vector2(xw + i.x, yh - i.y)) + + # left bottom + for i in bezier_iter(1f/self.border_detail[3].float, Vector2(self.border_radius[3], 0), + Vector2(0, 0), Vector2(0, self.border_radius[3])): + vertex.add(Vector2(x + i.x, yh + i.y)) + else: + glBegin(GL_QUAD_STRIP) + # left top + for i in bezier_iter(1f/self.border_detail[0].float, Vector2(0, -self.border_radius[0]), + Vector2(0, 0), Vector2(self.border_radius[0], 0)): + glColor4f(0, 0, 0, 0) + glVertex2f(x + i.x + self.shadow_offset.x, y + i.y - self.shadow_offset.y) + glColor(self.shadow_color) + glVertex2f(x + i.x, y + i.y) + + # right top + for i in bezier_iter(1f/self.border_detail[1].float, Vector2(-self.border_radius[1], 0), + Vector2(0, 0), Vector2(0, -self.border_radius[1])): + glColor4f(0, 0, 0, 0) + glVertex2f(xw + i.x + self.shadow_offset.x, y + i.y - self.shadow_offset.y) + glColor(self.shadow_color) + glVertex2f(xw + i.x, y + i.y) + + # right bottom + for i in bezier_iter(1f/self.border_detail[2].float, Vector2(0, -self.border_radius[2]), + Vector2(0, 0), Vector2(-self.border_radius[2], 0)): + glColor4f(0, 0, 0, 0) + glVertex2f(xw + i.x + self.shadow_offset.x, yh - i.y - self.shadow_offset.y) + glColor(self.shadow_color) + glVertex2f(xw + i.x, yh - i.y) + + # left bottom + for i in bezier_iter(1f/self.border_detail[3].float, Vector2(self.border_radius[3], 0), + Vector2(0, 0), Vector2(0, self.border_radius[3])): + glColor4f(0, 0, 0, 0) + glVertex2f(x + i.x + self.shadow_offset.x, yh + i.y - self.shadow_offset.y) + glColor(self.shadow_color) + glVertex2f(x + i.x, yh + i.y) + + glColor4f(0, 0, 0, 0) + glVertex2f(x + self.shadow_offset.x, y - self.border_radius[0] - self.shadow_offset.y) + glColor(self.shadow_color) + glVertex2f(x, y - self.border_radius[0]) + glEnd() + + +template drawTemplate*(drawtype, color, function, secondfunc: untyped): untyped = + ## Draws colorized vertexes + ## + ## Arguments: + ## - `drawtype` - draw type, like `GL_POLYGON` + ## - `color` - color for border drawing. + ## - `function` - function called before `glBegin` + ## - `secondfunc` - function called after `glEnd` + glColor4f(`color`.r, `color`.g, `color`.b, `color`.a) + `function` + glBegin(`drawtype`) + + for i in vertex: + glVertex2f(i.x, i.y) + + glEnd() + `secondfunc` + + +template drawTemplate*(drawtype, color, function, secondfunc: untyped, is_gradient: bool): untyped = + ## Draws colorized vertexes + ## + ## Arguments: + ## - `drawtype` - draw type, like `GL_POLYGON` + ## - `color` - color for border drawing. + ## - `function` - function called before `glBegin` + ## - `secondfunc` - function called after `glEnd` + ## - `is_gradient` - true when drawtype is `GL_POLYGON`. + glColor4f(`color`.r, `color`.g, `color`.b, `color`.a) + `function` + glBegin(`drawtype`) + + if is_gradient: + for i in 0..vertex.high: + let tmp = i/vertex.len() + if tmp < 0.25: + glColor(self.corners[0]) + elif tmp < 0.5: + glColor(self.corners[1]) + elif tmp < 0.75: + glColor(self.corners[2]) + else: + glColor(self.corners[3]) + glVertex2f(vertex[i].x, vertex[i].y) + else: + for i in vertex: + glVertex2f(i.x, i.y) + + glEnd() + `secondfunc` + +template drawTextureTemplate*(drawtype, color, function, secondfunc: untyped): untyped = + glEnable(GL_TEXTURE_2D) + glBindTexture(GL_TEXTURE_2D, self.texture.texture) + glColor4f(`color`.r, `color`.g, `color`.b, `color`.a) + `function` + glBegin(`drawtype`) + var + texture_size = self.texture.size + h = height + w = width + if texture_size.x < width: + let q = width / texture_size.x + texture_size.x *= q + texture_size.y *= q + + if texture_size.y < height: + let q = height / texture_size.y + texture_size.x *= q + texture_size.y *= q + + # crop .. :eyes: + let q = width / texture_size.x + texture_size.x *= q + texture_size.y *= q + h /= height/width + + for i in vertex: + glTexCoord2f((-x + i.x - w + texture_size.x) / texture_size.x, + (y - i.y - h + texture_size.y) / texture_size.y) + glVertex2f(i.x, i.y) + + glEnd() + `secondfunc` + glDisable(GL_TEXTURE_2D) + + + +# ----- Objects templates ----- # + +template drawablepattern*(`type`: untyped): untyped = + result = `type`( + texture: GlTextureObj(), border_width: 0, + border_detail: [8, 8, 8, 8], + border_radius: [0.float, 0, 0, 0], + border_color: Color(0, 0, 0, 0), + background_color: Color(0, 0, 0, 0), + shadow_offset: Vector2(0, 0), shadow: false, + shadow_color: standard_shadow_color + ) + +template nodepattern*(nodetype: untyped): untyped = + ## This used in childs of the NodeObj. + result = `nodetype`( + name: name, children: @[], + on_ready: handler_default, + on_process: handler_default, + on_input: event_handler_default, + on_enter: handler_default, + on_exit: handler_default, + on_theme_changed: handler_default, + is_ready: false, pausemode: INHERIT, visibility: VISIBLE + ) + result.type_of_node = NODE_TYPE_DEFAULT + +template node2dpattern*: untyped = + result.centered = false + result.timed_position = Vector2() + result.rect_size = Vector2() + result.rect_min_size = Vector2() + result.position = Vector2() + result.global_position = Vector2() + result.anchor = Anchor(0, 0, 0, 0) + result.size_anchor = Vector2() + result.z_index = 0f + result.z_index_global = 0f + result.relative_z_index = true + result.type_of_node = NODE_TYPE_2D + +template node3dpattern* = + result.rotation = Vector3() + result.translation = Vector3() + result.scale = Vector3(1, 1, 1) + result.global_rotation = Vector3() + result.global_translation = Vector3() + result.global_scale = Vector3(1, 1, 1) + result.type_of_node = NODE_TYPE_3D + +template controlpattern*: untyped = + result.hovered = false + result.focused = false + result.pressed = false + + result.mousemode = MOUSEMODE_SEE + result.rect_size = Vector2() + result.rect_min_size = Vector2() + result.position = Vector2() + result.global_position = Vector2() + result.size_anchor = Vector2() + result.anchor = Anchor(0, 0, 0, 0) + result.padding = Anchor(0, 0, 0, 0) + result.background = Drawable() + + result.on_mouse_enter = control_xy_handler + result.on_mouse_exit = control_xy_handler + result.on_click = control_xy_handler + result.on_press = control_xy_handler + result.on_release = control_xy_handler + result.on_focus = control_handler + result.on_unfocus = control_handler + result.type_of_node = NODE_TYPE_CONTROL + + + +# ----- GUI templates ----- # +template chartDrawAxis*(self: untyped) = + glColor(`self`.line_color) + glLineWidth(2) + glBegin(GL_LINE_STRIP) + glVertex2f(start_x, y) + glVertex2f(start_x, end_y) + glVertex2f(x + `self`.rect_size.x - `self`.rect_size.x/10, end_y) + glEnd() + + +template chartDrawRadar* = + let + value_step = max_val / 5 + radius_max = min(self.rect_size.x, self.rect_size.y)/2 + radius_step = radius_max/5 + center = Vector2(x + self.rect_size.x/2, y - self.rect_size.y/2) + angle_step = TAU / data.len.float + var + radius = radius_step + angle = 0f + val = value_step + glColor(current_theme~foreground) + glLineWidth(1) + for step in 0..5: + glBegin(GL_LINE_LOOP) + for i in data.low..data.high: + glVertex2f(center.x + cos(angle)*radius, center.y + sin(angle)*radius) + angle += angle_step + radius += radius_step + angle = 0f + glEnd() + + glBegin(GL_LINES) + for i in data.low..data.high: + glVertex2f(center.x + cos(angle)*radius_max, center.y + sin(angle)*radius_max) + glVertex2f(center.x, center.y) + angle += angle_step + angle = 0f + glEnd() + + glColor4f(chart_data.data_color.r, chart_data.data_color.g, chart_data.data_color.b, 0.8) + glBegin(GL_POLYGON) + for i in data.low..data.high: + let r = radius_max * (data[i][1].getNum() / max_val) + glVertex2f(center.x + cos(angle)*r, center.y + sin(angle)*r) + angle += angle_step + glEnd() + + angle = 0f + for i in data.low..data.high: + let + text = stext($data[i][0]) + size = text.getTextSize() + text.renderTo( + Vector2(center.x + cos(angle)*(radius_max+radius_step) - size.x/2, + center.y + sin(angle)*(radius_max+radius_step) + size.y), + size, Anchor()) + angle += angle_step + text.freeMemory() + + radius = radius_step + for step in 0..5: + let + text = stext($val, current_theme~foreground) + size = text.getTextSize() + text.setBold(true) + text.renderTo(Vector2(center.x - size.x, center.y + radius+radius_step/2), size, Anchor()) + radius += radius_step + val += value_step + text.freeMemory() + + +template chartDrawLine* = + glBegin(GL_LINE_STRIP) + for i in data.low..data.high: + let + j = i.float + h = max_height * (data[i][1].getNum() / max_val) + glVertex2f(start_x + section_width*j + section_width/2, end_y + h) + glEnd() + + +template chartDrawBar* = + let + height_step = max_height / 5 + value_step = max_val / 5 + var + height = height_step + value = value_step + for i in data.low..data.high: + let + j = i.float + h = max_height * (data[i][1].getNum() / max_val) + glColor(chart_data.data_color) + glRectf(start_x + section_width*j, end_y + h, start_x + section_width*(j+1), end_y) + + let + text = stext($data[i][0]) + value_text = stext($value) + size = text.getTextSize() + value_size = value_text.getTextSize() + text.renderTo(Vector2(start_x+section_width*j, end_y), size, Anchor()) + value_text.renderTo(Vector2(start_x - value_size.x - 2, end_y + height), size, Anchor()) + height += height_step + value += value_step + text.freeMemory() + value_text.freeMemory() + + +template chartDrawPie*(chart_data: untyped) = + let + d = `chart_data`.getSorted() + sum = `chart_data`.getSum() + radius = min(self.rect_size.x, self.rect_size.y)/2 + center = Vector2(x + self.rect_size.x/2, y - self.rect_size.y/2) + var + angle = PI/2 + a: float + for i in d.low..d.high: + glBegin(GL_TRIANGLE_FAN) + glVertex2f(center.x, center.y) + a = angle + angle += d[i][1].getNum() / sum * TAU + while a <= angle: + glVertex2f(center.x + cos(a)*radius, center.y + sin(a)*radius) + a += 0.01 + glEnd() + glColor4f(angle/6, angle/5, angle/4, 1f) + +template setTextTemplate*(self, `text`, `save_properties`, t: untyped): untyped = + ## Template for methods like `Label.setText`. + ## + ## Arguments: + ## - `self` - NodeRef; + ## - `text` - new text; + ## - `save_properties` - save style; + ## - `t` - StyleText field name; + var st = stext(`text`) + if `self`.`t`.font.isNil(): + `self`.`t`.font = standard_font + st.font = `self`.`t`.font + + if `save_properties`: + for i in 0..