Browse Source

little memory optimization ...

Ethosa 3 years ago
parent
commit
d7b6c4fced

+ 11 - 0
src/nodesnim/core/chartdata.nim

@@ -90,6 +90,17 @@ proc getNum*(val: ChartDataValue): float =
   of STRING_VALUE:
     0f
 
+proc `$`*(val: ChartDataValue): string =
+  case val.kind
+  of INTEGER_VALUE:
+    $val.ival
+  of FLOAT_VALUE:
+    $val.fval
+  of CHAR_VALUE:
+    $val.cval
+  of STRING_VALUE:
+    val.sval
+
 proc getSorted*(data: ChartData): seq[tuple[x, y: ChartDataValue]] =
   zip(data.x_axis, data.y_axis).sorted do (a, b: tuple[x, y: ChartDataValue]) -> int: cmp(a.y.getNum(), b.y.getNum())
 

+ 12 - 3
src/nodesnim/core/font.nim

@@ -24,6 +24,7 @@ type
   StyleText* = ref object
     font*: FontPtr
     rendered*: bool
+    need_free*: bool
     spacing*: float
     max_lines*: int
     texture*: GlTextureObj
@@ -41,7 +42,7 @@ proc schar*(c: string, color: ColorRef = nil,
 
 proc stext*(text: string, color: ColorRef = nil,
             style: cint = TTF_STYLE_NORMAL): StyleText =
-  result = StyleText(texture: GlTextureObj(size: Vector2()), spacing: 2, max_lines: -1)
+  result = StyleText(texture: GlTextureObj(size: Vector2()), spacing: 2, max_lines: -1, need_free: false)
   for i in text.utf8():
     result.chars.add(schar(i, color, style))
   result.font = standard_font
@@ -318,8 +319,9 @@ proc render*(text: StyleText, size: Vector2Obj, align: AnchorObj) =
     text.texture.size.y = surface.h.float
 
     # OpenGL:
-    if text.texture.texture == 0'u32:
-      glGenTextures(1, text.texture.texture.addr)
+    if text.texture.texture != 0'u32:
+      glDeleteTextures(1, addr text.texture.texture)
+    glGenTextures(1, addr text.texture.texture)
     glBindTexture(GL_TEXTURE_2D, text.texture.texture)
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
@@ -387,3 +389,10 @@ proc renderTo*(text: StyleText, pos, size: Vector2Obj, align: AnchorObj) =
     glEnd()
     glDisable(GL_TEXTURE_2D)
     glBindTexture(GL_TEXTURE_2D, 0)
+    if text.need_free:
+      glDeleteTextures(1, addr text.texture.texture)
+
+
+proc freeMemory*(text: StyleText) =
+  if text.texture.texture != 0'u32:
+    glDeleteTextures(1, addr text.texture.texture)

+ 0 - 1
src/nodesnim/nodescontrol/button.nim

@@ -71,7 +71,6 @@ method draw*(self: ButtonRef, w, h: GLfloat) =
       else:
         self.normal_background
 
-  self.text.rendered = false
   procCall self.LabelRef.draw(w, h)
 
 method duplicate*(self: ButtonRef, obj: var ButtonObj): ButtonRef {.base.} =

+ 138 - 75
src/nodesnim/nodescontrol/chart.nim

@@ -3,11 +3,13 @@
 import
   ../thirdparty/opengl,
 
+  ../core/anchor,
   ../core/enums,
   ../core/color,
   ../core/vector2,
   ../core/chartdata,
   ../core/themes,
+  ../core/font,
 
   ../nodes/node,
 
@@ -40,6 +42,137 @@ 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)
@@ -50,13 +183,7 @@ method draw*(self: ChartRef, w, h: GLfloat) =
     end_y = y - self.rect_size.y + self.rect_size.y/10
 
   if self.hasAxis():
-    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()
+    self.drawAxis()
 
   for chart_data in self.data:
     let
@@ -66,79 +193,15 @@ method draw*(self: ChartRef, w, h: GLfloat) =
       section_width = (self.rect_size.x - self.rect_size.x/5) / data.len.float
 
     glColor(chart_data.data_color)
-
     case chart_data.chart_type
     of LINE_CHART:
-      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()
-
+      drawLine()
     of BAR_CHART:
-      for i in data.low..data.high:
-        let
-          j = i.float
-          h = max_height * (data[i][1].getNum() / max_val)
-        glRectf(start_x + section_width*j, end_y + h, start_x + section_width*(j+1), end_y)
-
+      drawBar()
     of PIE_CHART:
-      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)
-
+      chart_data.drawPie()
     of RADAR_CHART:
-      let
-        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
-      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()
+      drawRadar()
 
 
 method addChartData*(self: ChartRef, chart_data: ChartData) {.base.} =

+ 1 - 0
src/nodesnim/nodescontrol/checkbox.nim

@@ -72,6 +72,7 @@ method draw*(self: CheckBoxRef, w, h: GLfloat) =
   self.rect_min_size = self.text.getTextSize()
   self.rect_min_size.x += 36
   self.resize(self.rect_size.x, self.rect_size.y)
+  self.text.freeMemory()
 
   self.box.draw(x+4, y-4, 24, 24)
   if self.enabled:

+ 0 - 1
src/nodesnim/nodescontrol/subwindow.nim

@@ -52,7 +52,6 @@ proc SubWindow*(name: string = "SubWindow"): SubWindowRef =
   result.visibility = GONE
   result.title = Label("Title")
   result.title.text = stext"Title"
-  result.title.text.rendered = false
   result.title.parent = result
   result.left_taked = false
   result.right_taked = false

+ 1 - 1
tests/test3.nim

@@ -392,7 +392,7 @@ suite "Work with Control nodes.":
               @["one", "two", "three", "four", "five"],
               @[10, 24, 18, 32, 4], "myData", current_theme~accent_dark, RADAR_CHART))
           move(700, 450)
-          resize(128, 128)
+          resize(196, 196)
 
     getSceneByName("main").addChildren(spiderweb_chart)