Parcourir la source

add runtime scene loader for https://github.com/Ethosa/nodesnim/issues/28

Ethosa il y a 3 ans
Parent
commit
63af13c901

+ 4 - 4
src/nodesnim/core/font.nim

@@ -40,7 +40,6 @@ proc stext*(text: string, color: ColorRef = Color(1f, 1f, 1f),
   result = StyleText(texture: GlTextureObj(size: Vector2()), spacing: 2, max_lines: -1)
   for i in text.utf8():
     result.chars.add(schar(i, color, style))
-  result.font = standard_font
   result.rendered = false
 
 
@@ -273,9 +272,10 @@ proc renderSurface*(text: StyleText, align: AnchorObj): SurfacePtr =
   ##
   ## Arguments:
   ##   - `align` -- text align.
-  when defined(debug):
-    if text.font.isNil():
-      throwError(ResourceError, "Font isn't loaded!")
+  if text.font.isNil():
+    text.font = standard_font
+  if text.font.isNil():
+    throwError(ResourceError, "Font isn't loaded!")
 
   if not text.font.isNil() and $text != "":
     let

+ 15 - 0
src/nodesnim/nodes/node.nim

@@ -256,6 +256,13 @@ method delete*(self: NodeRef) {.base.} =
     self.parent.removeChild(self)
 
 
+method `[]`*(self: NodeRef, index: int): NodeRef {.base, inline.} =
+  self.getChild(index)
+
+method `~`*(self: NodeRef, path: string): NodeRef {.base, inline.} =
+  self.getNode(path)
+
+
 # --- Macros --- #
 import
   macros
@@ -393,6 +400,14 @@ macro `@`*(node: NodeRef, event_name, code: untyped): untyped =
         proc(`self`: SliderRef, `arg`: uint) =
           `code`
 
+  of "ontextchanged":
+    var name = event_name[0]
+    event_name.expectParams(@["self", "arg"])
+    result = quote do:
+      `node`.`name` =
+        proc(`self`: LabelRef, `arg`: string) =
+          `code`
+
   of "onedit":
     var name = event_name[0]
     event_name.expectParams(@["self", "arg"])

+ 2 - 4
src/nodesnim/nodescontrol/button.nim

@@ -31,8 +31,6 @@ type
     on_touch*: ButtonTouchHandler ## This called, when user clicks on button.
   ButtonRef* = ref ButtonObj
 
-let touch_handler*: ButtonTouchHandler = proc(self: ButtonRef, x, y: float) = discard
-
 
 proc Button*(name: string = "Button"): ButtonRef =
   ## Creates a new Button node.
@@ -55,8 +53,8 @@ proc Button*(name: string = "Button"): ButtonRef =
   result.normal_background.setColor(Color(0x444444ff))
   result.hover_background.setColor(Color(0x505050ff))
   result.press_background.setColor(Color(0x595959ff))
-  result.on_touch = touch_handler
-  result.on_text_changed = text_changed_handler
+  result.on_touch = proc(self: ButtonRef, x, y: float) = discard
+  result.on_text_changed = proc(self: LabelRef, text: string) = discard
   result.kind = BUTTON_NODE
 
 

+ 2 - 3
src/nodesnim/nodescontrol/edittext.nim

@@ -34,7 +34,6 @@ type
 const
   BLINK_TIME: uint8 = 15
   BLINK_WIDTH: float = 2
-let edit_handler*: EditHandler = proc(k: string) = discard
 
 
 proc EditText*(name: string = "EditText", hint: string = "Edit text ..."): EditTextRef =
@@ -52,8 +51,8 @@ proc EditText*(name: string = "EditText", hint: string = "Edit text ..."): EditT
   result.hint.setColor(Color("#ccc"))
   result.text.setColor(Color("#555"))
   result.text_align = Anchor(0, 0, 0, 0)
-  result.on_edit = edit_handler
-  result.on_text_changed = text_changed_handler
+  result.on_edit = proc(k: string) = discard
+  result.on_text_changed = proc(self: LabelRef, text: string) = discard
   result.kind = EDIT_TEXT_NODE
   
   if result.text.chars.len() > result.hint.chars.len():

+ 1 - 3
src/nodesnim/nodescontrol/label.nim

@@ -31,8 +31,6 @@ type
     text*: StyleText
   LabelRef* = ref LabelObj
 
-let text_changed_handler*: TextChangedHandler = proc(self: LabelRef, text: string) = discard
-
 
 proc Label*(name: string = "Label"): LabelRef =
   ## Creates a new Label.
@@ -47,7 +45,7 @@ proc Label*(name: string = "Label"): LabelRef =
   result.rect_size.y = 40
   result.text = stext""
   result.text_align = Anchor(0, 0, 0, 0)
-  result.on_text_changed = text_changed_handler
+  result.on_text_changed = proc(self: LabelRef, text: string) = discard
   result.kind = LABEL_NODE
 
 

+ 1 - 3
src/nodesnim/nodescontrol/slider.nim

@@ -26,8 +26,6 @@ type
     on_changed*: SliderChangedHandler
   SliderRef* = ref SliderObj
 
-let slider_changed_handler*: SliderChangedHandler =
-    proc(self: SliderRef, new_value: uint) = discard
 
 proc Slider*(name: string = "Slider"): SliderRef =
   ## Creates a new Slider.
@@ -47,7 +45,7 @@ proc Slider*(name: string = "Slider"): SliderRef =
   result.progress_color = Color(0.5, 0.5, 0.5)
   result.max_value = 100
   result.value = 0
-  result.on_changed = slider_changed_handler
+  result.on_changed = proc(self: SliderRef, new_value: uint) = discard
   result.kind = SLIDER_NODE
 
 

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

@@ -50,7 +50,8 @@ proc SubWindow*(name: string = "SubWindow"): SubWindowRef =
   result.rect_size.y = 220
   result.visibility = GONE
   result.title = Label("Title")
-  result.title.setText("Title")
+  result.title.text = stext"Title"
+  result.title.text.rendered = false
   result.title.parent = result
   result.left_taked = false
   result.right_taked = false

+ 1 - 3
src/nodesnim/nodescontrol/switch.nim

@@ -24,8 +24,6 @@ type
     on_switch*: SwitchHandler  ## This called when switch toggled.
   SwitchRef* = ref SwitchObj
 
-let switch_handler*: SwitchHandler = proc(self: SwitchRef, toggled: bool) = discard
-
 
 proc Switch*(name: string = "Switch"): SwitchRef =
   ## Creates a new Switch.
@@ -43,7 +41,7 @@ proc Switch*(name: string = "Switch"): SwitchRef =
   result.value = false
   result.rect_size.x = 50
   result.rect_size.y = 20
-  result.on_switch = switch_handler
+  result.on_switch = proc(self: SwitchRef, toggled: bool) = discard
   result.kind = COLOR_RECT_NODE
 
 

+ 2 - 5
src/nodesnim/nodescontrol/texture_button.nim

@@ -31,9 +31,6 @@ type
     on_touch*: TextureButtonTouchHandler  ## This called, when user clicks on button.
   TextureButtonRef* = ref TextureButtonObj
 
-let texture_btn_touch_handler*: TextureButtonTouchHandler =
-    proc(self: TextureButtonRef, x, y: float) = discard
-
 
 proc TextureButton*(name: string = "TextureButton"): TextureButtonRef =
   ## Creates a new TextureButton node.
@@ -53,8 +50,8 @@ proc TextureButton*(name: string = "TextureButton"): TextureButtonRef =
   result.normal_background_texture = GlTextureObj()
   result.hover_background_texture = GlTextureObj()
   result.press_background_texture = GlTextureObj()
-  result.on_touch = texture_btn_touch_handler
-  result.on_text_changed = text_changed_handler
+  result.on_touch = proc(self: TextureButtonRef, x, y: float) = discard
+  result.on_text_changed = proc(self: LabelRef, text: string) = discard
   result.kind = TEXTURE_BUTTON_NODE
 
 

+ 140 - 0
src/nodesnim/runtime/scene_loader.nim

@@ -0,0 +1,140 @@
+# author: Ethosa
+## Uses for runtime scene loading.
+import
+  ../core,
+  ../nodes,
+  ../nodescontrol,
+  ../nodes2d,
+  ../nodes3d,
+
+  xmltree,
+  xmlparser,
+  strtabs,
+  tables,
+  strutils,
+  macros
+
+
+var parsable = {
+  # default
+  "Node": Node, "Scene": Scene, "AudioStreamPlayer": AudioStreamPlayer,
+  "AnimationPlayer": AnimationPlayer,
+  # control
+  "Control": Control, "Box": Box, "VBox": VBox, "HBox": HBox,
+  "ColorRect": ColorRect, "Label": Label,"Button": Button, 
+  "EditText": proc(name: string = "EditText"): EditTextRef = EditText(name, "Edit text ..."),
+  "TextureButton": TextureButton, "TextureRect": TextureRect,
+  "TextureProgressBar": TextureProgressBar, "Switch": Switch,
+  "ToolTip": proc(name: string = "ToolTip"): ToolTipRef = ToolTip(name, "ToolTip"),
+  "SubWindow": SubWindow, "Scroll": Scroll, "ProgressBar": ProgressBar, "Slider": Slider,
+  "Popup": Popup, "Counter": Counter,
+  # 2D
+  "Node2D": Node2D, "Sprite": Sprite, "Sprite2D", "CollisionShape2D": CollisionShape2D,
+  "KinematicBody2D": KinematicBody2D, "TileMap": TileMap, "Camera2D": Camera2D,
+  "YSort": YSort,
+  # 3D
+  "Node3D": Node3D, "Sprite3D": Sprite3D, "Camera3D": Camera3D,
+  "GeometryInstance": proc(name: string = "GeometryInstance"): GeometryInstanceRef =
+                      GeometryInstance(name, GEOMETRY_CUBE)
+}.toTable()
+
+
+var properties = initTable[system.string, proc (node: NodeRef, value: string)]()
+macro `!`(props, fn, code: untyped): untyped =
+  let
+    node = ident("node")
+    value = ident("value")
+  result = quote do:
+    `props`[`fn[1]`] =
+      proc(`node`: NodeRef, `value`: string) =
+        `code`
+
+properties!"color":
+  node.ColorRectRef.color = Color(value)
+
+properties!"name":
+  node.name = value
+
+properties!"text":
+  node.LabelRef.setText(value)
+
+properties!"style":
+  if node.type_of_node == NODE_TYPE_CONTROL:
+    var styles = StyleSheet()
+    for item in value.split(";"):
+      var style_info = item.split(":")
+      styles[style_info[0]] =  style_info[1]
+    node.ControlRef.setStyle(styles)
+
+properties!"image":
+  node.TextureRectRef.loadTexture(value)
+
+properties!"texture":
+  node.SpriteRef.loadTexture(value)
+
+properties!"2dtexture":
+  node.Sprite3DRef.loadTexture(value)
+
+properties!"anchor":
+  let val = value.split(Whitespace)
+  if val.len == 1:
+    let v = parseFloat(val[0])
+    node.ControlRef.setAnchor(v, v, v, v)
+  elif val.len == 4:
+    node.ControlRef.setAnchor(parseFloat(val[0]), parseFloat(val[1]),
+                                parseFloat(val[2]), parseFloat(val[3]))
+
+properties!"size_anchor":
+  let val = value.split(Whitespace)
+  if val.len == 1:
+    let v = parseFloat(val[0])
+    node.ControlRef.setSizeAnchor(v, v)
+  elif val.len == 2:
+    node.ControlRef.setSizeAnchor(parseFloat(val[0]), parseFloat(val[1]))
+
+properties!"background_color":
+  node.ControlRef.setBackgroundColor(Color(value))
+
+properties!"row":
+  node.GridBoxRef.setRow(parseInt(value))
+
+properties!"cell":
+  node.GridBoxRef.setRow(parseInt(value))
+
+
+
+proc xmlAttr(xml: XmlNode, node: NodeRef) =
+  if not xml.attrs.isNil():
+    for attr, fn in properties.pairs:
+      if xml.attrs.hasKey(attr):
+        fn(node, xml.attrs[attr])
+
+
+proc xmlNode(xml: XmlNode, level: var seq[NodeRef]) =
+  ## Converts xml tree to nodes.
+  if level.len > 0 and parsable.hasKey(xml.tag):
+    for key, node in parsable.pairs:
+      if key == xml.tag:
+        level[^1].addChild(node(key))
+  level.add(level[^1].children[^1])
+
+  # properties
+  xmlAttr(xml, level[^1])
+
+  # children
+  for child in xml.items:
+    xmlNode(child, level)
+
+  if level.len > 0:
+    discard level.pop()
+
+
+
+proc loadScene*(file: string): NodeRef =
+  ## Loads the scene from XML file.
+  result = Scene(file.rsplit(".", 1)[0])
+  var
+    xml = loadXml(file)
+    level: seq[NodeRef] = @[]
+  level.add(result)
+  xmlNode(xml, level)

+ 8 - 0
src/nodesnim/runtime/test_scene.xml

@@ -0,0 +1,8 @@
+<Node
+    name="myOwnNode"
+    >
+    <Label
+        text="hello, world!"
+        >
+    </Label>
+</Node>