Browse Source

add Control and ColorRect nodes.

Ethosa 5 years ago
parent
commit
095d2cb842

+ 3 - 2
src/nodesnim.nim

@@ -17,11 +17,12 @@ import
   nodesnim/nodes/scene,
   nodesnim/nodes/canvas,
 
-  nodesnim/nodescontrol/control
+  nodesnim/nodescontrol/control,
+  nodesnim/nodescontrol/color_rect
 
 export
   opengl, glut,
   window, environment,
   vector2, rect2, enums, anchor, color, exceptions, input,
   node, scene, canvas,
-  control
+  control, color_rect

+ 11 - 1
src/nodesnim/nodes/node.nim

@@ -42,7 +42,7 @@ template nodepattern*(nodetype: untyped): untyped =
     enter: proc() = discard,
     exit: proc() = discard,
     is_ready: false, pausemode: INHERIT, visible: true,
-    anchor: nil
+    anchor: Anchor(0, 0, 0, 0)
   )
   result = variable.addr
 
@@ -162,6 +162,9 @@ method getPauseMode*(self: NodePtr): PauseMode {.base.} =
     current = current.parent
     result = current.pausemode
 
+method isParentOf*(self, other: NodePtr): bool {.base, inline.} =
+  other in self.children
+
 method handle*(self: NodePtr, event: InputEvent, mouse_on: var NodePtr) {.base.} =
   ## Handles user input.
   ## This used in the Window object.
@@ -181,6 +184,9 @@ method hasNode*(self: NodePtr, other: NodePtr): bool {.base.} =
   ## - `other`: other node.
   self.getChildIndex(other) != -1
 
+method hasParent*(self: NodePtr): bool {.base, inline.} =
+  self.parent != nil
+
 method move*(self: NodePtr, x, y: float) {.base, inline.} =
   ## Adds `x` and` y` to the node position.
   ##
@@ -195,6 +201,10 @@ method move*(self: NodePtr, vec2: Vector2Ref) {.base, inline.} =
   ## Arguments:
   ## - `vec2`: how much to add to the position on the X,Y axes.
   self.position += vec2
+  self.anchor.x1 = 0
+  self.anchor.x2 = 0
+  self.anchor.y1 = 0
+  self.anchor.y2 = 0
 
 method removeChild*(self: NodePtr, index: int) {.base.} =
   ## Removes node child at a specific position.

+ 10 - 2
src/nodesnim/nodes/scene.nim

@@ -44,9 +44,17 @@ method exit*(scene: ScenePtr) {.base.} =
     child.is_ready = false
 
 method handleScene*(scene: ScenePtr, event: InputEvent, mouse_on: var NodePtr, paused: bool) {.base.} =
+  var childs = scene.getChildIter()
+  for i in countdown(childs.len()-1, 0):
+    if paused and childs[i].getPauseMode() != PROCESS:
+      continue
+    if childs[i].visible:
+      childs[i].handle(event, mouse_on)
+      childs[i].input(event)
+
+method reAnchorScene*(scene: ScenePtr, paused: bool) {.base.} =
   for child in scene.getChildIter():
     if paused and child.getPauseMode() != PROCESS:
       continue
     if child.visible:
-      child.handle(event, mouse_on)
-    child.input(event)
+      child.calcPositionAnchor()

+ 43 - 0
src/nodesnim/nodescontrol/color_rect.nim

@@ -0,0 +1,43 @@
+# author: Ethosa
+import
+  ../thirdparty/opengl,
+
+  ../core/vector2,
+  ../core/rect2,
+  ../core/anchor,
+  ../core/input,
+  ../core/color,
+
+  ../nodes/node,
+  control
+
+
+type
+  ColorRectObj* = object of ControlPtr
+    color*: ColorRef
+  ColorRectPtr* = ptr ColorRectObj
+
+
+proc ColorRect*(name: string, variable: var ColorRectObj): ColorRectPtr =
+  nodepattern(ColorRectObj)
+  controlpattern()
+  variable.color = Color(1f, 1f, 1f)
+  variable.rect_size.x = 40
+  variable.rect_size.y = 40
+
+proc ColorRect*(obj: var ColorRectObj): ColorRectPtr {.inline.} =
+  ColorRect("ColorRect", obj)
+
+
+method draw*(self: ColorRectPtr, w, h: GLfloat) =
+  self.calcGlobalPosition()
+  let
+    x = -w/2 + self.global_position.x
+    y = h/2 - self.global_position.y
+
+  glColor4f(self.color.r, self.color.g, self.color.b, self.color.a)
+  glRectf(x, y, x + self.rect_size.x, y - self.rect_size.y)
+
+  # Press
+  if self.pressed:
+    self.press(last_event.x, last_event.y)

+ 67 - 0
src/nodesnim/nodescontrol/control.nim

@@ -1,5 +1,7 @@
 # author: Ethosa
 import
+  ../thirdparty/opengl,
+
   ../core/vector2,
   ../core/rect2,
   ../core/anchor,
@@ -13,10 +15,75 @@ type
   ControlObj* = object of CanvasObj
     hovered*: bool
     pressed*: bool
+    focused*: bool
 
     mouse_enter*: proc(x, y: float): void
     mouse_exit*: proc(x, y: float): void
     click*: proc(x, y: float): void
     press*: proc(x, y: float): void
     release*: proc(x, y: float): void
+    focus*: proc(): void
+    unfocus*: proc(): void
   ControlPtr* = ptr ControlObj
+
+
+template controlpattern*: untyped =
+  variable.hovered = false
+  variable.focused = false
+  variable.pressed = false
+
+  variable.mouse_enter = proc(x, y: float) = discard
+  variable.mouse_exit = proc(x, y: float) = discard
+  variable.click = proc(x, y: float) = discard
+  variable.press = proc(x, y: float) = discard
+  variable.release = proc(x, y: float) = discard
+  variable.focus = proc() = discard
+  variable.unfocus = proc() = discard
+
+proc Control*(name: string, variable: var ControlObj): ControlPtr =
+  nodepattern(ControlObj)
+  controlpattern()
+
+proc Control*(obj: var ControlObj): ControlPtr {.inline.} =
+  Control("Control", obj)
+
+
+method calcPositionAnchor*(self: ControlPtr) =
+  if self.parent != nil:
+    self.position.x = self.parent.rect_size.x*self.anchor.x1 - self.rect_size.x*self.anchor.x2
+    self.position.y = self.parent.rect_size.y*self.anchor.y1 - self.rect_size.y*self.anchor.y2
+
+method draw*(self: ControlPtr, w, h: GLfloat) =
+  {.warning[LockLevel]: off.}
+  self.calcGlobalPosition()
+  # Press
+  if self.pressed:
+    self.press(last_event.x, last_event.y)
+
+method handle*(self: ControlPtr, event: InputEvent, mouse_on: var NodePtr) =
+  {.warning[LockLevel]: off.}
+  let hasmouse = Rect2(self.global_position, self.rect_size).hasPoint(event.x, event.y)
+  if mouse_on == nil and hasmouse:
+    mouse_on = self
+    # Hover
+    if not self.hovered:
+      self.mouse_enter(event.x, event.y)
+      self.hovered = true
+    else:
+      self.mouse_exit(event.x, event.y)
+      self.hovered = false
+    # Focus
+    if not self.focused:
+      self.focused = true
+      self.focus()
+    # Click
+    if mouse_pressed and not self.pressed:
+      self.pressed = true
+      self.click(event.x, event.y)
+  # Unfocus
+  if self.focused:
+    self.unfocus()
+  if not mouse_pressed and self.pressed:
+    self.pressed = false
+    self.release(event.x, event.y)
+

+ 19 - 14
src/nodesnim/window.nim

@@ -42,11 +42,28 @@ proc display {.cdecl.} =
   # Draw current scene.
   current_scene.drawScene(width.GLfloat, height.GLfloat, paused)
   press_state = -1
+  mouse_on = nil
 
   # Update window.
   glFlush()
   glutSwapBuffers()
 
+
+proc reshape(w, h: cint) {.cdecl.} =
+  ## This called when window resized.
+  if w > 0 and h > 0:
+    glViewport(0, 0, w, h)
+    glMatrixMode(GL_PROJECTION)
+    glLoadIdentity()
+    glOrtho(-w.GLdouble/2, w.GLdouble/2, -h.GLdouble/2, h.GLdouble/2, -1, 1)
+    glMatrixMode(GL_MODELVIEW)
+    glLoadIdentity()
+    width = w
+    height = h
+
+    if current_scene != nil:
+      current_scene.reAnchorScene(paused)
+
 template check(event, condition, conditionelif: untyped): untyped =
   if last_event is `event` and `condition`:
     press_state = 2
@@ -112,19 +129,6 @@ proc motion(x, y: cint) {.cdecl.} =
   current_scene.handleScene(last_event, mouse_on, paused)
 
 
-proc reshape(w, h: cint) {.cdecl.} =
-  ## This called when window resized.
-  if w > 0 and h > 0:
-    glViewport(0, 0, w, h)
-    glMatrixMode(GL_PROJECTION)
-    glLoadIdentity()
-    glOrtho(-w.GLdouble/2, w.GLdouble/2, -h.GLdouble/2, h.GLdouble/2, -1, 1)
-    glMatrixMode(GL_MODELVIEW)
-    glLoadIdentity()
-    width = w
-    height = h
-
-
 # ---- Public ---- #
 proc addScene*(scene: ScenePtr) =
   ## Adds a new scenes in app.
@@ -141,6 +145,7 @@ proc changeScene*(name: string): bool {.discardable.} =
       current_scene = nil
       current_scene = scene
       current_scene.enter()
+      current_scene.reAnchorScene(paused)
       result = true
       break
 
@@ -170,7 +175,7 @@ proc Window*(title: cstring, w: cint = 640, h: cint = 360) {.cdecl.} =
   reshape(w, h)
 
 
-proc windowLauch* =
+proc windowLaunch* =
   ## Start main window loop.
   glutDisplayFunc(display)
   glutIdleFunc(display)

+ 1 - 1
tests/test1.nim

@@ -15,4 +15,4 @@ var
 
 addScene(main)        # Add new scene in window.
 setMainScene("Main")  # Set main scene.
-windowLauch()         # Start main loop.
+windowLaunch()         # Start main loop.

+ 1 - 1
tests/test2.nim

@@ -24,4 +24,4 @@ canvas.move(74.4, 89.4)
 
 addScene(main)
 setMainScene("Main")
-windowLauch()
+windowLaunch()

+ 1 - 1
tests/test3.nim

@@ -47,4 +47,4 @@ node.input =
 
 addScene(main)
 setMainScene("Main")
-windowLauch()
+windowLaunch()

+ 21 - 0
tests/test4.nim

@@ -0,0 +1,21 @@
+# --- Test 4. Use ColorRect node. --- #
+import nodesnim
+
+
+Window("hello world")
+
+var
+  mainobj: SceneObj
+  main = Scene("Main", mainobj)
+
+  colorrectobj: ColorRectObj
+  colorrect = ColorRect(colorrectobj)
+
+main.addChild(colorrect)
+
+colorrect.color = Color(1f, 1f, 1f)  # default ColorRect color.
+
+
+addScene(main)
+setMainScene("Main")
+windowLaunch()