浏览代码

add SubWindow node.

SakiKawasaki 5 年之前
父节点
当前提交
c2e23dc893

+ 2 - 0
README.md

@@ -72,6 +72,7 @@ This section contains links to documentation for all nodes.
 |                    |                          |[TextureProgressBar][tprogress]|                            |                             |
 |                    |                          |[Counter][Counter]             |                            |                             |
 |                    |                          |[Switch][Switch]               |                            |                             |
+|                    |                          |[SubWindow][swindow]           |                            |                             |
 
 
 
@@ -156,6 +157,7 @@ Use the [`Nim compiler user guide`](https://nim-lang.org/docs/nimc.html#dynlibov
 [tprogress]:https://ethosa.github.io/nodesnim/nodesnim/nodescontrol/texture_progress_bar.html
 [Counter]:https://ethosa.github.io/nodesnim/nodesnim/nodescontrol/counter.html
 [Switch]:https://ethosa.github.io/nodesnim/nodesnim/nodescontrol/switch.html
+[swindow]:https://ethosa.github.io/nodesnim/nodesnim/nodescontrol/subwindow.html
 
 [Node2D]:https://ethosa.github.io/nodesnim/nodesnim/nodes2d/node2d.html
 [Sprite]:https://ethosa.github.io/nodesnim/nodesnim/nodes2d/sprite.html

+ 2 - 1
src/nodesnim.nim

@@ -61,6 +61,7 @@ import
   nodesnim/nodescontrol/texture_progress_bar,
   nodesnim/nodescontrol/counter,
   nodesnim/nodescontrol/switch,
+  nodesnim/nodescontrol/subwindow,
 
   nodesnim/nodes2d/node2d,
   nodesnim/nodes2d/sprite,
@@ -86,7 +87,7 @@ export
   # Control nodes
   control, color_rect, texture_rect, label, button, box, hbox, vbox, grid_box, edittext,
   rich_label, rich_edit_text, scroll, progress_bar, vprogress_bar, slider, vslider, popup,
-  texture_button, texture_progress_bar, counter, switch,
+  texture_button, texture_progress_bar, counter, switch, subwindow,
   # 2D nodes
   node2d, sprite, animated_sprite, ysort, collision_shape2d, kinematic_body2d, camera2d,
   # 3D nodes

+ 4 - 0
src/nodesnim/core/enums.nim

@@ -17,6 +17,7 @@ type
     CANVAS_NODE,
     SCENE_NODE,
     AUDIO_STREAM_PLAYER_NODE,
+    # 2D nodes
     COLLISION_SHAPE_2D_NODE,
     YSORT_NODE,
     CAMERA_2D_NODE,
@@ -24,6 +25,7 @@ type
     ANIMATED_SPRITE_NODE,
     NODE2D_NODE,
     KINEMATIC_BODY_2D_NODE,
+    # Control nodes
     BOX_NODE,
     BUTTON_NODE,
     COLOR_RECT_NODE,
@@ -45,6 +47,8 @@ type
     VBOX_NODE,
     VPROGRESS_BAR_NODE,
     VSLIDER_NODE,
+    SUB_WINDOW_NODE,
+    # 3D nodes
     NODE3D_NODE,
     GEOMETRY_INSTANCE_NODE
   NodeTypes* {.pure.} = enum

+ 5 - 4
src/nodesnim/nodescontrol/edittext.nim

@@ -247,10 +247,11 @@ method handle*(self: EditTextRef, event: InputEvent, mouse_on: var NodeRef) =
   ## Handles user input. Thi uses in the `window.nim`.
   procCall self.ControlRef.handle(event, mouse_on)
 
-  if self.hovered:  # Change cursor, if need
-    glutSetCursor(GLUT_CURSOR_TEXT)
-  else:
-    glutSetCursor(GLUT_CURSOR_LEFT_ARROW)
+  when not defined(android) and not defined(ios):
+    if self.hovered:  # Change cursor, if need
+      glutSetCursor(GLUT_CURSOR_TEXT)
+    else:
+      glutSetCursor(GLUT_CURSOR_LEFT_ARROW)
 
   if event.kind == MOUSE and event.pressed:
     self.caret_position = self.getCharPositionUnderMouse()

+ 13 - 0
src/nodesnim/nodescontrol/label.nim

@@ -93,6 +93,19 @@ method draw*(self: LabelRef, w, h: GLfloat) =
   if self.pressed:
     self.on_press(self, last_event.x, last_event.y)
 
+method getTextSize*(self: LabelRef): Vector2Ref {.base.} =
+  ## Returns text size.
+  result = Vector2()
+  for line in self.text.splitLines():  # get text height
+    var x: float = 0f
+    for c in line:
+      x += self.font.glutBitmapWidth(c.int).float
+    if x > result.x:
+      result.x = x
+    result.y += self.spacing + self.size
+  if result.y > 0:
+    result.y -= self.spacing
+
 method duplicate*(self: LabelRef): LabelRef {.base.} =
   ## Duplicates Label object and create a new Label.
   self.deepCopy()

+ 5 - 4
src/nodesnim/nodescontrol/rich_edit_text.nim

@@ -239,10 +239,11 @@ method handle*(self: RichEditTextRef, event: InputEvent, mouse_on: var NodeRef)
   ## Handles user input. This uses in the `window.nim`.
   procCall self.ControlRef.handle(event, mouse_on)
 
-  if self.hovered:  # Change cursor, if need
-    glutSetCursor(GLUT_CURSOR_TEXT)
-  else:
-    glutSetCursor(GLUT_CURSOR_LEFT_ARROW)
+  when not defined(android) and not defined(ios):
+    if self.hovered:  # Change cursor, if need
+      glutSetCursor(GLUT_CURSOR_TEXT)
+    else:
+      glutSetCursor(GLUT_CURSOR_LEFT_ARROW)
 
   if event.kind == MOUSE and event.pressed:
     self.caret_position = self.getCharPositionUnderMouse()

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

@@ -0,0 +1,268 @@
+# author: Ethosa
+## Extended version of SubWindow node.
+import
+  ../thirdparty/opengl,
+  ../thirdparty/opengl/glut,
+
+  ../core/vector2,
+  ../core/rect2,
+  ../core/anchor,
+  ../core/input,
+  ../core/enums,
+  ../core/color,
+  ../core/image,
+
+  ../nodes/node,
+  control,
+  popup,
+  label
+
+
+type
+  SubWindowObj* = object of PopupObj
+    left_taked*, right_taked*, top_taked*, bottom_taked*: bool
+    title_taked*: bool
+    icon*: GlTextureObj
+    title_bar_color*: ColorRef
+    border_color*: ColorRef
+    title_taked_pos*: Vector2Ref
+    title*: LabelRef
+  SubWindowRef* = ref SubWindowObj
+
+
+proc SubWindow*(name: string = "SubWindow"): SubWindowRef =
+  ## Creates a new SubWindow.
+  ##
+  ## Arguments:
+  ## - `name` is a node name.
+  runnableExamples:
+    var window = SubWindow("SubWindow")
+  nodepattern(SubWindowRef)
+  controlpattern()
+  result.background_color = Color(0x454545ff)
+  result.title_bar_color = Color(0x303030ff)
+  result.border_color = Color(0x212121ff)
+  result.rect_size.x = 320
+  result.rect_size.y = 220
+  result.visible = false
+  result.title = Label("Title")
+  result.title.setText("Title")
+  result.title.parent = result
+  result.left_taked = false
+  result.right_taked = false
+  result.top_taked = false
+  result.bottom_taked = false
+  result.title_taked = false
+  result.title_taked_pos = Vector2()
+  result.icon = GlTextureObj(texture: 0)
+  result.kind = SUB_WINDOW_NODE
+
+
+method close*(self: SubWindowRef) {.base.} =
+  ## Closes the window. alias of hide() method.
+  self.hide()
+
+
+method draw*(self: SubWindowRef, w, h: GLfloat) =
+  ## This uses in the `window.nim`.
+  let
+    x = -w/2 + self.global_position.x
+    y = h/2 - self.global_position.y
+
+  glColor4f(self.background_color.r, self.background_color.g, self.background_color.b, self.background_color.a)
+  glRectf(x, y, x + self.rect_size.x, y - self.rect_size.y)
+
+  for child in self.getChildIter():
+    child.calcGlobalPosition()
+    if child.global_position.x > self.global_position.x + self.rect_size.x:
+      child.visible = false
+    elif child.global_position.y > self.global_position.y + self.rect_size.y:
+      child.visible = false
+    elif child.global_position.x + child.rect_size.x < self.global_position.x:
+      child.visible = false
+    elif child.global_position.y + child.rect_size.y < self.global_position.y:
+      child.visible = false
+    else:
+      child.visible = true
+
+  glColor4f(self.border_color.r, self.border_color.g, self.border_color.b, self.border_color.a)
+  glBegin(GL_LINE_LOOP)
+  glVertex2f(x, y)
+  glVertex2f(x+self.rect_size.x, y)
+  glVertex2f(x+self.rect_size.x, y-self.rect_size.y)
+  glVertex2f(x, y-self.rect_size.y)
+  glEnd()
+
+  glBegin(GL_QUADS)
+
+  glColor4f(self.background_color.r, self.background_color.g, self.background_color.b, self.background_color.a)
+  glVertex2f(x+1, y-32)
+  glVertex2f(x + self.rect_size.x - 1, y-32)
+  glVertex2f(x + self.rect_size.x - 1, y - self.rect_size.y + 32)
+  glVertex2f(x+1, y - self.rect_size.y + 32)
+
+  glColor4f(self.title_bar_color.r, self.title_bar_color.g, self.title_bar_color.b, self.title_bar_color.a)
+  glVertex2f(x+1, y-1)
+  glVertex2f(x + self.rect_size.x - 1, y-1)
+  glVertex2f(x + self.rect_size.x - 1, y-31)
+  glVertex2f(x+1, y-31)
+
+  glEnd()
+
+  let size = self.title.getTextSize()
+  self.title.position.x = self.rect_size.x / 2 - size.x / 2
+  self.title.position.y = 1 + 15 - size.y / 2
+  self.title.calcGlobalPosition()
+  self.title.draw(w, h)
+
+  if self.icon.texture > 0:
+    glEnable(GL_TEXTURE_2D)
+    glBindTexture(GL_TEXTURE_2D, self.icon.texture)
+    glBegin(GL_QUADS)
+    glTexCoord2f(0, 0)
+    glVertex2f(x+2, y-2)
+    glTexCoord2f(0, 1)
+    glVertex2f(x+2, y - 28)
+    glTexCoord2f(1, 1)
+    glVertex2f(x + 28, y - 28)
+    glTexCoord2f(1, 0)
+    glVertex2f(x + 28, y-2)
+    glEnd()
+    glDisable(GL_TEXTURE_2D)
+
+  # Press
+  if self.pressed:
+    self.on_press(self, last_event.x, last_event.y)
+
+
+method duplicate*(self: SubWindowRef): SubWindowRef {.base.} =
+  ## Duplicates SubWindow object and create a new SubWindow.
+  self.deepCopy()
+
+
+method handle*(self: SubWindowRef, event: InputEvent, mouse_on: var NodeRef) =
+  ## This uses in the `window.nim`.
+  procCall self.ControlRef.handle(event, mouse_on)
+
+  let
+    left = event.x >= self.global_position.x-1 and event.x <= self.global_position.x+2
+    right = event.x <= self.global_position.x+self.rect_size.x+1 and event.x >= self.global_position.x+self.rect_size.x-1
+    top = event.y >= self.global_position.y-1 and event.y <= self.global_position.y+2
+    bottom = event.y <= self.global_position.y+self.rect_size.y+1 and event.y >= self.global_position.y+self.rect_size.y-1
+    title = Rect2(self.global_position+2, Vector2(self.rect_size.x-4, 32)).contains(event.x, event.y)
+
+  when not defined(android) and not defined(ios):
+    if left and top:
+      glutSetCursor(GLUT_CURSOR_TOP_LEFT_CORNER)
+    elif left and bottom:
+      glutSetCursor(GLUT_CURSOR_BOTTOM_LEFT_CORNER)
+    elif right and top:
+      glutSetCursor(GLUT_CURSOR_TOP_RIGHT_CORNER)
+    elif right and bottom:
+      glutSetCursor(GLUT_CURSOR_BOTTOM_RIGHT_CORNER)
+    elif left or right:
+      glutSetCursor(GLUT_CURSOR_LEFT_RIGHT)
+    elif bottom or top:
+      glutSetCursor(GLUT_CURSOR_UP_DOWN)
+    else:
+      glutSetCursor(GLUT_CURSOR_LEFT_ARROW)
+
+  if event.kind == MOUSE:
+    if event.pressed:
+      if left and top:
+        self.left_taked = true
+        self.top_taked = true
+      elif left and bottom:
+        self.left_taked = true
+        self.bottom_taked = true
+      elif right and top:
+        self.right_taked = true
+        self.top_taked = true
+      elif right and bottom:
+        self.right_taked = true
+        self.bottom_taked = true
+
+      elif left:
+        self.left_taked = true
+      elif right:
+        self.right_taked = true
+      elif bottom:
+        self.bottom_taked = true
+      elif top:
+        self.top_taked = true
+
+      if title:
+        self.title_taked = true
+        self.title_taked_pos = Vector2(self.global_position.x - event.x, self.global_position.y - event.y)
+    else:
+      self.left_taked = false
+      self.right_taked = false
+      self.top_taked = false
+      self.bottom_taked = false
+      self.title_taked = false
+
+  let
+    left_p = self.global_position.x - event.x
+    right_p = self.global_position.x + self.rect_size.x - event.x
+    top_p = self.global_position.y - event.y
+    bottom_p = self.global_position.y + self.rect_size.y - event.y
+
+  if self.left_taked and self.rect_size.x + left_p > 128:
+    self.position.x -= left_p
+    self.rect_size.x += left_p
+
+  if self.right_taked and self.rect_size.x - right_p > 128:
+    self.rect_size.x -= right_p
+
+  if self.top_taked and self.rect_size.y + top_p > 64:
+    self.position.y -= top_p
+    self.rect_size.y += top_p
+
+  if self.bottom_taked and self.rect_size.y - bottom_p > 64:
+    self.rect_size.y -= bottom_p
+
+  if self.title_taked:
+    self.position.x -= self.global_position.x - event.x
+    self.position.y -= self.global_position.y - event.y
+    self.position += self.title_taked_pos
+
+
+method open*(self: SubWindowRef) {.base.} =
+  ## Opens the window. alias of show() method.
+  self.show()
+
+
+method resize*(self: SubWindowRef, w, h: float) {.base.} =
+  ## Resizes subwindow, if available.
+  ##
+  ## Arguments:
+  ## - `w` is a new width.
+  ## - `h` is a new height.
+  if w > 128:
+    self.rect_size.x = w
+  if h > 64:
+    self.rect_size.y = h
+
+
+method setTitle*(self: SubWindowRef, title: string) {.base.} =
+  ## Changes subwindow title.
+  ##
+  ## Arguments:
+  ## - `title` is a new title.
+  self.title.setText(title)
+
+
+method setIcon*(self: SubWindowRef, gltexture: GlTextureObj) {.base.} =
+  ## Changes icon.
+  ##
+  ## Arguments:
+  ## - `gltexture` is a texture, loaded via load(file, mode=GL_RGB).
+  self.icon = gltexture
+
+
+method setIcon*(self: SubWindowRef, file: cstring) {.base.} =
+  ## Loads icon from file.
+  ##
+  ## Arguments:
+  ## - `file` is an image file path.
+  self.icon = load(file)

+ 1 - 0
tests/README.md

@@ -39,3 +39,4 @@
 37. [Use Camera2D node.](https://github.com/Ethosa/nodesnim/blob/master/tests/test37.nim)
 38. [Use Node3D.](https://github.com/Ethosa/nodesnim/blob/master/tests/test38.nim)
 39. [Use GeometryInstance node.](https://github.com/Ethosa/nodesnim/blob/master/tests/test39.nim)
+40. [Use SubWindow node.](https://github.com/Ethosa/nodesnim/blob/master/tests/test40.nim)

+ 19 - 0
tests/test40.nim

@@ -0,0 +1,19 @@
+# --- Test 40. Use SubWindow node. --- #
+import nodesnim
+
+
+Window("subwindow ._.")
+
+var
+  main = Scene()
+  window = SubWindow()
+
+
+main.addChild(window)
+window.move(64, 64)
+window.setIcon("assets/anim/0.jpg")
+window.open()
+
+
+addMainScene(main)
+windowLaunch()