|
|
|
|
|
|
|
|
|
|
|
|
|
|
from .display import Display |
|
|
from .display import Display |
|
|
from .events import Events |
|
|
from .events import Events |
|
|
|
|
|
from .resource import Manager |
|
|
import pygame |
|
|
import pygame |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Node: |
|
|
class Node: |
|
|
def __init__(self, name="Node", parent=None): |
|
|
def __init__(self, name="Node", parent=None): |
|
|
self._parent = None |
|
|
|
|
|
self._name = name |
|
|
|
|
|
self._children = [] |
|
|
|
|
|
|
|
|
self._NODE_DATA={ |
|
|
|
|
|
"parent":None, |
|
|
|
|
|
"name":name, |
|
|
|
|
|
"children":[] |
|
|
|
|
|
"resource":None |
|
|
|
|
|
} |
|
|
if parent is not None: |
|
|
if parent is not None: |
|
|
try: |
|
|
try: |
|
|
self.parent = parent |
|
|
self.parent = parent |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
@property |
|
|
def parent(self): |
|
|
def parent(self): |
|
|
return self._parent |
|
|
|
|
|
|
|
|
return self._NODE_DATA["parent"] |
|
|
|
|
|
|
|
|
@parent.setter |
|
|
@parent.setter |
|
|
def parent(self, new_parent): |
|
|
def parent(self, new_parent): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
@property |
|
|
def root(self): |
|
|
def root(self): |
|
|
if self._parent is None: |
|
|
|
|
|
|
|
|
if self.parent is None: |
|
|
return self |
|
|
return self |
|
|
return self._parent.root |
|
|
|
|
|
|
|
|
return self.parent.root |
|
|
|
|
|
|
|
|
@property |
|
|
@property |
|
|
def name(self): |
|
|
def name(self): |
|
|
return self._name |
|
|
|
|
|
|
|
|
return self._NODE_DATA["name"] |
|
|
|
|
|
|
|
|
@name.setter |
|
|
@name.setter |
|
|
def name(self, value): |
|
|
def name(self, value): |
|
|
if self._parent is not None: |
|
|
|
|
|
if self._parent.get_node(value) is not None: |
|
|
|
|
|
|
|
|
if self.parent is not None: |
|
|
|
|
|
if self.parent.get_node(value) is not None: |
|
|
raise NodeError("Parent already contains node named '{}'.".format(name)) |
|
|
raise NodeError("Parent already contains node named '{}'.".format(name)) |
|
|
self._name = value |
|
|
|
|
|
|
|
|
self._NODE_DATA["name"] = value |
|
|
|
|
|
|
|
|
@property |
|
|
@property |
|
|
def full_name(self): |
|
|
def full_name(self): |
|
|
if self._parent is None: |
|
|
|
|
|
return self._name |
|
|
|
|
|
return self._parent.full_name + "." + self._name |
|
|
|
|
|
|
|
|
if self.parent is None: |
|
|
|
|
|
return self.name |
|
|
|
|
|
return self.parent.full_name + "." + self.name |
|
|
|
|
|
|
|
|
@property |
|
|
@property |
|
|
def child_count(self): |
|
|
def child_count(self): |
|
|
return len(this._children) |
|
|
|
|
|
|
|
|
return len(this._NODE_DATA["children"]) |
|
|
|
|
|
|
|
|
def parent_to_node(self, parent, allow_reparenting=False): |
|
|
def parent_to_node(self, parent, allow_reparenting=False): |
|
|
if not isinstance(value, Node): |
|
|
if not isinstance(value, Node): |
|
|
raise NodeError("Node may only parent to another Node instance.") |
|
|
raise NodeError("Node may only parent to another Node instance.") |
|
|
if self._parent is None or self._parent != parent: |
|
|
|
|
|
if self._parent is not None: |
|
|
|
|
|
|
|
|
if self.parent is None or self.parent != parent: |
|
|
|
|
|
if self.parent is not None: |
|
|
if allow_Reparenting == False: |
|
|
if allow_Reparenting == False: |
|
|
raise NodeError("Node already assigned a parent Node.") |
|
|
raise NodeError("Node already assigned a parent Node.") |
|
|
if self._parent.remove_node(self) != self: |
|
|
|
|
|
|
|
|
if self.parent.remove_node(self) != self: |
|
|
raise NodeError("Failed to remove self from current parent.") |
|
|
raise NodeError("Failed to remove self from current parent.") |
|
|
try: |
|
|
try: |
|
|
parent.attach_node(self) |
|
|
parent.attach_node(self) |
|
|
|
|
|
|
|
|
raise NodeError("Failed to remove given node from it's current parent.") |
|
|
raise NodeError("Failed to remove given node from it's current parent.") |
|
|
if self.get_node(node.name) is not None: |
|
|
if self.get_node(node.name) is not None: |
|
|
raise NodeError("Node with name '{}' already attached.".format(node.name)) |
|
|
raise NodeError("Node with name '{}' already attached.".format(node.name)) |
|
|
node._parent = self |
|
|
|
|
|
if index < 0 or index >= len(self._children): |
|
|
|
|
|
self._children.append(node) |
|
|
|
|
|
|
|
|
node._NODE_DATA["parent"] = self |
|
|
|
|
|
children = self._NODE_DATA["children"] |
|
|
|
|
|
if index < 0 or index >= len(children): |
|
|
|
|
|
children.append(node) |
|
|
else: |
|
|
else: |
|
|
self._children.insert(index, node) |
|
|
|
|
|
|
|
|
children.insert(index, node) |
|
|
|
|
|
|
|
|
def remove_node(self, node): |
|
|
def remove_node(self, node): |
|
|
if isinstance(node, (str, unicode)): |
|
|
if isinstance(node, (str, unicode)): |
|
|
|
|
|
|
|
|
return node.parent.remove_node(node) |
|
|
return node.parent.remove_node(node) |
|
|
except NodeError as e: |
|
|
except NodeError as e: |
|
|
raise e |
|
|
raise e |
|
|
if node in self._children: |
|
|
|
|
|
self._children.remove(node) |
|
|
|
|
|
node._parent = None |
|
|
|
|
|
|
|
|
if node in self._NODE_DATA["children"]: |
|
|
|
|
|
self._NODE_DATA["children"].remove(node) |
|
|
|
|
|
node._NODE_DATA["parent"] = None |
|
|
return node |
|
|
return node |
|
|
else: |
|
|
else: |
|
|
raise NodeError("Expected a Node instance or a string.") |
|
|
raise NodeError("Expected a Node instance or a string.") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_node(self, name): |
|
|
def get_node(self, name): |
|
|
if len(self._children) <= 0: |
|
|
|
|
|
|
|
|
if self.child_count <= 0: |
|
|
return None |
|
|
return None |
|
|
|
|
|
|
|
|
subnames = name.split(".") |
|
|
subnames = name.split(".") |
|
|
for c in self._children: |
|
|
|
|
|
|
|
|
for c in self._NODE_DATA["children"]: |
|
|
if c.name == subnames[0]: |
|
|
if c.name == subnames[0]: |
|
|
if len(subnames) > 1: |
|
|
if len(subnames) > 1: |
|
|
return c.get_node(".".join(subnames[1:-1])) |
|
|
return c.get_node(".".join(subnames[1:-1])) |
|
|
|
|
|
|
|
|
if hasattr(self, "on_update"): |
|
|
if hasattr(self, "on_update"): |
|
|
self.on_update(dt) |
|
|
self.on_update(dt) |
|
|
|
|
|
|
|
|
for c in self._children: |
|
|
|
|
|
|
|
|
for c in self._NODE_DATA["children"]: |
|
|
c._update(dt) |
|
|
c._update(dt) |
|
|
|
|
|
|
|
|
def _render(self, surface): |
|
|
def _render(self, surface): |
|
|
for c in self._children: |
|
|
|
|
|
|
|
|
for c in self._NODE_DATA["children"]: |
|
|
c._render(surface) |
|
|
c._render(surface) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Node2D(Node): |
|
|
class Node2D(Node): |
|
|
def __init__(self, name="Node2D", parent=None): |
|
|
def __init__(self, name="Node2D", parent=None): |
|
|
try: |
|
|
try: |
|
|
|
|
|
|
|
|
self.on_render() |
|
|
self.on_render() |
|
|
del self._ACTIVE_SURF |
|
|
del self._ACTIVE_SURF |
|
|
|
|
|
|
|
|
def blit(self, img, pos=(0,0), rect=None): |
|
|
|
|
|
|
|
|
def draw_image(self, img, pos=(0,0), rect=None): |
|
|
if not hasattr(self, "_ACTIVE_SURF"): |
|
|
if not hasattr(self, "_ACTIVE_SURF"): |
|
|
return |
|
|
return |
|
|
self._ACTIVE_SURF.blit(img, pos, rect) |
|
|
self._ACTIVE_SURF.blit(img, pos, rect) |
|
|
|
|
|
|
|
|
Node2D.__init__(self, name, parent) |
|
|
Node2D.__init__(self, name, parent) |
|
|
except NodeError as e: |
|
|
except NodeError as e: |
|
|
raise e |
|
|
raise e |
|
|
|
|
|
# TODO: Update this class to use the _NODE*_DATA={} structure. |
|
|
self._offset = (0.0, 0.0) |
|
|
self._offset = (0.0, 0.0) |
|
|
self._scale = (1.0, 1.0) |
|
|
self._scale = (1.0, 1.0) |
|
|
self._scaleToDisplay = False |
|
|
self._scaleToDisplay = False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NodeSprite(Node2D): |
|
|
|
|
|
def __init__(self, name="NodeSprite", parent=None): |
|
|
|
|
|
try: |
|
|
|
|
|
Node2D.__init__(self, name, parent) |
|
|
|
|
|
except NodeError as e: |
|
|
|
|
|
raise e |
|
|
|
|
|
self._NODESPRITE_DATA={ |
|
|
|
|
|
"rect":[0,0,0,0], |
|
|
|
|
|
"image":"", |
|
|
|
|
|
"scale":[1.0, 1.0], |
|
|
|
|
|
"surface":None |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def rect(self): |
|
|
|
|
|
return (self._NODESPRITE_DATA["rect"][0], |
|
|
|
|
|
self._NODESPRITE_DATA["rect"][1], |
|
|
|
|
|
self._NODESPRITE_DATA["rect"][2], |
|
|
|
|
|
self._NODESPRITE_DATA["rect"][3]) |
|
|
|
|
|
|
|
|
|
|
|
@rect.setter |
|
|
|
|
|
def rect(self, rect): |
|
|
|
|
|
if not isinstance(rect, (list, tuple)): |
|
|
|
|
|
raise TypeError("Expected a list or tuple.") |
|
|
|
|
|
if len(rect) != 4: |
|
|
|
|
|
raise ValueError("rect value contains wrong number of values.") |
|
|
|
|
|
try: |
|
|
|
|
|
self.rect_x = rect[0] |
|
|
|
|
|
self.rect_y = rect[1] |
|
|
|
|
|
self.rect_width = rect[2] |
|
|
|
|
|
self.rect_height = rect[3] |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
raise e |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def rect_x(self): |
|
|
|
|
|
return self._NODESPRITE_DATA["rect"][0] |
|
|
|
|
|
@rect_x.setter |
|
|
|
|
|
def rect_x(self, v): |
|
|
|
|
|
if not isinstance(v, int): |
|
|
|
|
|
raise TypeError("Expected integer value.") |
|
|
|
|
|
self._NODESPRITE_DATA["rect"][0] = v |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def rect_y(self): |
|
|
|
|
|
return self._NODESPRITE_DATA["rect"][1] |
|
|
|
|
|
@rect_y.setter |
|
|
|
|
|
def rect_y(self, v): |
|
|
|
|
|
if not isinstance(v, int): |
|
|
|
|
|
raise TypeError("Expected integer value.") |
|
|
|
|
|
self._NODESPRITE_DATA["rect"][1] = v |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def rect_width(self): |
|
|
|
|
|
return self._NODESPRITE_DATA["rect"][2] |
|
|
|
|
|
@rect_width.setter |
|
|
|
|
|
def rect_width(self, v): |
|
|
|
|
|
if not isinstance(v, int): |
|
|
|
|
|
raise TypeError("Expected integer value.") |
|
|
|
|
|
self._NODESPRITE_DATA["rect"][2] = v |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def rect_height(self): |
|
|
|
|
|
return self._NODESPRITE_DATA["rect"][3] |
|
|
|
|
|
@rect_height.setter |
|
|
|
|
|
def rect_height(self, v): |
|
|
|
|
|
if not isinstance(v, int): |
|
|
|
|
|
raise TypeError("Expected integer value.") |
|
|
|
|
|
self._NODESPRITE_DATA["rect"][3] = v |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def center(self): |
|
|
|
|
|
r = self._NODESPRITE_DATA["rect"] |
|
|
|
|
|
return (int(r[0] + (r[2] * 0.5)), int(r[1] + (r[3] * 0.5))) |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def scale(self): |
|
|
|
|
|
return (self._NODESPRITE_DATA["scale"][0], self._NODESPRITE_DATA["scale"][1]) |
|
|
|
|
|
@scale.setter(self, scale): |
|
|
|
|
|
if not isinstance(scale, (list, tuple)): |
|
|
|
|
|
raise TypeError("Expected a list or tuple.") |
|
|
|
|
|
if len(scale) != 2: |
|
|
|
|
|
raise ValueError("Scale contains wrong number of values.") |
|
|
|
|
|
try: |
|
|
|
|
|
self.scale_x = scale[0] |
|
|
|
|
|
self.scale_y = scale[1] |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
raise e |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def scale_x(self): |
|
|
|
|
|
return self._NODESPRITE_DATA["scale"][0] |
|
|
|
|
|
@scale_x.setter |
|
|
|
|
|
def scale_x(self, v): |
|
|
|
|
|
if not isinstance(v, (int, float)): |
|
|
|
|
|
raise TypeError("Expected number value.") |
|
|
|
|
|
self._NODESPRITE_DATA["scale"][0] = float(v) |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def scale_y(self): |
|
|
|
|
|
return self._NODESPRITE_DATA["scale"][1] |
|
|
|
|
|
@scale_y.setter |
|
|
|
|
|
def scale_y(self, v): |
|
|
|
|
|
if not isinstance(v, (int, float)): |
|
|
|
|
|
raise TypeError("Expected number value.") |
|
|
|
|
|
self._NODESPRITE_DATA["scale"][1] = float(v) |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def image(self): |
|
|
|
|
|
return self._NODESPRITE_DATA["image"] |
|
|
|
|
|
@image.setter |
|
|
|
|
|
def image(self, image): |
|
|
|
|
|
if self._NODESPRITE_DATA["image"] != "": |
|
|
|
|
|
self._NODESPRITE_DATA["surface"] = None # Clear reference to original surface. |
|
|
|
|
|
pass |