|
|
@@ -5,7 +5,7 @@ |
|
|
|
Python Version: 3.7 |
|
|
|
''' |
|
|
|
|
|
|
|
NODETYPE_NODE = "NODE" |
|
|
|
from .display import Display |
|
|
|
|
|
|
|
class NodeError(Exception): |
|
|
|
pass |
|
|
@@ -23,10 +23,6 @@ class Node: |
|
|
|
raise e |
|
|
|
|
|
|
|
@property |
|
|
|
def type(self): |
|
|
|
return NODETYPE_NODE |
|
|
|
|
|
|
|
@property |
|
|
|
def parent(self): |
|
|
|
return self._parent |
|
|
|
|
|
|
@@ -144,17 +140,222 @@ class Node: |
|
|
|
for c in self._children: |
|
|
|
c._render(surface) |
|
|
|
|
|
|
|
|
|
|
|
class Node2D(Node): |
|
|
|
def __init__(self, name="Node2D", parent=None): |
|
|
|
try: |
|
|
|
Node.__init__(self, name, parent) |
|
|
|
except NodeError as e: |
|
|
|
raise e |
|
|
|
|
|
|
|
def _render(self, surface): |
|
|
|
Node._render(self, surface) |
|
|
|
|
|
|
|
if hasattr(self, "on_render"): |
|
|
|
self.on_render(surface) |
|
|
|
self._ACTIVE_SURF = surface |
|
|
|
self.on_render() |
|
|
|
del self._ACTIVE_SURF |
|
|
|
|
|
|
|
def blit(self, img, pos=(0,0), rect=None): |
|
|
|
if not hasattr(self, "_ACTIVE_SURF"): |
|
|
|
return |
|
|
|
self._ACTIVE_SURF.blit(img, pos, rect) |
|
|
|
|
|
|
|
def fill(self, color): |
|
|
|
if not hasattr(self, "_ACTIVE_SURF"): |
|
|
|
return |
|
|
|
self._ACTIVE_SURF.fill(color) |
|
|
|
|
|
|
|
def draw_lines(points, color, thickness=1, closed=False): |
|
|
|
if not hasattr(self, "_ACTIVE_SURF"): |
|
|
|
return |
|
|
|
pygame.draw.lines(self._ACTIVE_SURF, color, closed, points, thickness) |
|
|
|
|
|
|
|
def draw_rect(rect, color, thinkness=1): |
|
|
|
if not hasattr(self, "_ACTIVE_SURF"): |
|
|
|
return |
|
|
|
pygame.draw.rect(self._ACTIVE_SURF, color, rect, thickness) |
|
|
|
|
|
|
|
def draw_ellipse(rect, color, thickness=1, fill_color=None): |
|
|
|
if not hasattr(self, "_ACTIVE_SURF"): |
|
|
|
return |
|
|
|
if fill_color is not None: |
|
|
|
pygame.draw.ellipse(self._ACTIVE_SURF, fill_color, rect) |
|
|
|
if thickness > 0: |
|
|
|
pygame.draw.ellipse(self._ACTIVE_SURF, color, rect, thickness) |
|
|
|
|
|
|
|
def draw_circle(pos, radius, color, thickness=1, fill_color=None): |
|
|
|
if not hasattr(self, "_ACTIVE_SURF"): |
|
|
|
return |
|
|
|
if fill_color is not None: |
|
|
|
pygame.draw.circle(self._ACTIVE_SURF, fill_color, pos, radius) |
|
|
|
if thickness > 0: |
|
|
|
pygame.draw.circle(self._ACTIVE_SURF, color, pos, radius, thickness) |
|
|
|
|
|
|
|
def draw_polygon(points, color, thickness=1, fill_color=None): |
|
|
|
if not hasattr(self, "_ACTIVE_SURF"): |
|
|
|
return |
|
|
|
if fill_color is not None: |
|
|
|
pygame.draw.polygon(self._ACTIVE_SURF, fill_color, points) |
|
|
|
if thickness >= 1: |
|
|
|
pygame.draw.polygon(self._ACTIVE_SURF, color, points, thickness) |
|
|
|
|
|
|
|
|
|
|
|
class NodeSurface(Node): |
|
|
|
def __init__(self, name="NodeSurface", parent=None, display_ref=None): |
|
|
|
|
|
|
|
|
|
|
|
class NodeSurface(Node2D): |
|
|
|
def __init__(self, name="NodeSurface", parent=None): |
|
|
|
try: |
|
|
|
Node.__init__(self, name, parent) |
|
|
|
Node2D.__init__(self, name, parent) |
|
|
|
except NodeError as e: |
|
|
|
raise e |
|
|
|
self._offset = (0.0, 0.0) |
|
|
|
self._scale = (1.0, 1.0) |
|
|
|
self._keepAspectRatio = False |
|
|
|
self._surface = None |
|
|
|
self._tsurface = None |
|
|
|
self.set_surface() |
|
|
|
|
|
|
|
def _updateTransformSurface(self): |
|
|
|
if self._surface is None: |
|
|
|
return |
|
|
|
if self._scale[0] == 1.0 and self._scale[1] == 1.0: |
|
|
|
self._tsurface = None |
|
|
|
size = self._surface.get_size() |
|
|
|
nw = size[0] * self._scale[0] |
|
|
|
nh = 0 |
|
|
|
if self._keepAspectRatio: |
|
|
|
nh = size[1] * self._scale[0] |
|
|
|
else: |
|
|
|
nh = size[1] * self._scale[1] |
|
|
|
self._tsurface = pygame.Surface((nw, nh), pygame.SRCALPHA, self._surface) |
|
|
|
|
|
|
|
@property |
|
|
|
def resolution(self): |
|
|
|
if self._surface is None: |
|
|
|
return (0,0) |
|
|
|
return self._surface.get_size() |
|
|
|
@resolution.setter |
|
|
|
def resolution(self, res): |
|
|
|
try: |
|
|
|
self.set_surface(res) |
|
|
|
except (TypeError, ValueError) as e: |
|
|
|
raise e |
|
|
|
|
|
|
|
@property |
|
|
|
def width(self): |
|
|
|
return self.resolution[0] |
|
|
|
|
|
|
|
@property |
|
|
|
def height(self): |
|
|
|
return self.resolution[1] |
|
|
|
|
|
|
|
@property |
|
|
|
def offset(self): |
|
|
|
return self._offset |
|
|
|
@offset.setter(self, offset): |
|
|
|
if not isinstance(offset, tuple): |
|
|
|
raise TypeError("Expected a tuple") |
|
|
|
if len(offset) != 2: |
|
|
|
raise ValueError("Expected tuple of length two.") |
|
|
|
if not isinstance(offset[0], (int, float)) or not isinstance(offset[1], (int, float)): |
|
|
|
raise TypeError("Expected number values.") |
|
|
|
self._offset = (float(offset[0]), float(offset[1])) |
|
|
|
|
|
|
|
@property |
|
|
|
def offset_x(self): |
|
|
|
return self._offset[0] |
|
|
|
@offset_x.setter |
|
|
|
def offset_x(self, x): |
|
|
|
if not isinstance(x, (int, float)): |
|
|
|
raise TypeError("Expected number value.") |
|
|
|
self._offset = (x, self._offset[1]) |
|
|
|
|
|
|
|
@property |
|
|
|
def offset_y(self): |
|
|
|
return self._offset[1] |
|
|
|
@offset_y.setter |
|
|
|
def offset_y(self, y): |
|
|
|
if not isinstance(y, (int, float)): |
|
|
|
raise TypeError("Expected number value.") |
|
|
|
self._offset = (self._offset[0], y) |
|
|
|
|
|
|
|
@property |
|
|
|
def scale(self): |
|
|
|
return self._scale |
|
|
|
@scale.setter |
|
|
|
def scale(self, scale): |
|
|
|
if self._keepAspectRatio: |
|
|
|
if not isinstance(scale, (int, float)): |
|
|
|
raise TypeError("Expected number value.") |
|
|
|
self._scale = (scale, self._scale[1]) |
|
|
|
else: |
|
|
|
if not isinstance(scale, tuple): |
|
|
|
raise TypeError("Expected a tuple") |
|
|
|
if len(scale) != 2: |
|
|
|
raise ValueError("Expected tuple of length two.") |
|
|
|
if not isinstance(scale[0], (int, float)) or not isinstance(scale[1], (int, float)): |
|
|
|
raise TypeError("Expected number values.") |
|
|
|
self._scale = scale |
|
|
|
self._updateTransformSurface() |
|
|
|
|
|
|
|
@property |
|
|
|
def keep_aspect_ratio(self): |
|
|
|
return self._keepAspectRatio |
|
|
|
@keep_aspect_ratio.setter |
|
|
|
def keep_aspect_ratio(self, keep): |
|
|
|
self._keepAspectRatio = (keep == True) |
|
|
|
self._updateTransformSurface() |
|
|
|
|
|
|
|
def scale_to(self, target_resolution): |
|
|
|
if self._surface is not None: |
|
|
|
size = self._surface.get_size() |
|
|
|
nscale = (float(size[0]) / float(target_resolution[0]), float(size[1]) / float(target_resolution[1])) |
|
|
|
self.scale = nscale |
|
|
|
|
|
|
|
|
|
|
|
def set_surface(self, resolution=None): |
|
|
|
dsurf = Display.surface |
|
|
|
if resolution is None: |
|
|
|
if dsurf is not None: |
|
|
|
self._surface = dsurf.convert_alpha() |
|
|
|
self._updateTransformSurface() |
|
|
|
else: |
|
|
|
if not isinstance(r, tuple): |
|
|
|
raise TypeError("Expected a tuple.") |
|
|
|
if len(r) != 2: |
|
|
|
raise ValueError("Expected a tuple of length two.") |
|
|
|
if not isinstance(r[0], int) or not isinstance(r[1], int): |
|
|
|
raise TypeError("Tuple expected to contain integers.") |
|
|
|
if dsurf is not None: |
|
|
|
self._surface = pygame.Surface(resolution, pygame.SRCALPHA, dsurf) |
|
|
|
else: |
|
|
|
self._surface = pygame.Surface(resolution, pygame.SRCALPHA) |
|
|
|
self._updateTransformSurface() |
|
|
|
|
|
|
|
def _render(self, surface): |
|
|
|
if self._surface is None: |
|
|
|
self.set_surface() |
|
|
|
if self._surface is not None: |
|
|
|
Node2D._render(self, self._surface) |
|
|
|
else: |
|
|
|
Node2D._render(self, surface) |
|
|
|
self._scale_and_blit(surface) |
|
|
|
|
|
|
|
|
|
|
|
def _scale_and_blit(self, dest): |
|
|
|
dsize = dest.get_size() |
|
|
|
pos = (int(self._offset[0]), int(self._offset[1])) |
|
|
|
|
|
|
|
src = self._surface |
|
|
|
if self._tsurface is not None: |
|
|
|
pygame.transform.scale(self._surface, self._tsurface.get_size(), self._tsurface) |
|
|
|
src = self._tsurface |
|
|
|
if ssize[0] == dsize[0] and ssize[1] == dsize[1]: |
|
|
|
dest.blit(src, pos) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|