| @@ -7,7 +7,7 @@ | |||
| from .display import Display | |||
| from .events import Events | |||
| from .resource import Manager | |||
| from .resource import ResourceManager | |||
| import pygame | |||
| @@ -20,7 +20,7 @@ class Node: | |||
| self._NODE_DATA={ | |||
| "parent":None, | |||
| "name":name, | |||
| "children":[] | |||
| "children":[], | |||
| "resource":None | |||
| } | |||
| if parent is not None: | |||
| @@ -165,15 +165,54 @@ class Node2D(Node): | |||
| Node.__init__(self, name, parent) | |||
| except NodeError as e: | |||
| raise e | |||
| self._NODE2D_DATA={ | |||
| "position":[0.0, 0.0] | |||
| } | |||
| def _render(self, surface): | |||
| Node._render(self, surface) | |||
| @property | |||
| def position(self): | |||
| p = self._NODE2D_DATA["position"] | |||
| return (p[0], p[1]) | |||
| @position.setter | |||
| def position(self, pos): | |||
| if not isinstance(pos, (list, tuple)): | |||
| raise TypeError("Expected a list or tuple.") | |||
| if len(pos) != 2: | |||
| raise ValueError("Wrong number of values given.") | |||
| try: | |||
| self.position_x = pos[0] | |||
| self.position_y = pos[1] | |||
| except Exception as e: | |||
| raise e | |||
| @property | |||
| def position_x(self): | |||
| return self._NODE2D_DATA["position"][0] | |||
| @position_x.setter | |||
| def position_x(self, v): | |||
| if not isinstance(v, (int, float)): | |||
| raise TypeError("Excepted an number value.") | |||
| self._NODE2D_DATA["position"][0] = float(v) | |||
| @property | |||
| def position_y(self): | |||
| return self._NODE2D_DATA["position"][1] | |||
| @position_y.setter | |||
| def position_y(self, v): | |||
| if not isinstance(v, (int, float)): | |||
| raise TypeError("Excepted an number value.") | |||
| self._NODE2D_DATA["position"][1] = float(v) | |||
| def _callOnRender(self, surface): | |||
| if hasattr(self, "on_render"): | |||
| self._ACTIVE_SURF = surface | |||
| self.on_render() | |||
| del self._ACTIVE_SURF | |||
| def _render(self, surface): | |||
| self._callOnRender(surface) | |||
| Node._render(self, surface) | |||
| def draw_image(self, img, pos=(0,0), rect=None): | |||
| if not hasattr(self, "_ACTIVE_SURF"): | |||
| return | |||
| @@ -228,7 +267,6 @@ class NodeSurface(Node2D): | |||
| except NodeError as e: | |||
| raise e | |||
| # TODO: Update this class to use the _NODE*_DATA={} structure. | |||
| self._offset = (0.0, 0.0) | |||
| self._scale = (1.0, 1.0) | |||
| self._scaleToDisplay = False | |||
| self._scaleDirty = False | |||
| @@ -284,38 +322,7 @@ class NodeSurface(Node2D): | |||
| @property | |||
| def height(self): | |||
| return self.resolution[1] | |||
| @property | |||
| def offset(self): | |||
| return self._offset | |||
| @offset.setter | |||
| def offset(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) | |||
| return self.resolution[1] | |||
| @property | |||
| def scale(self): | |||
| @@ -413,8 +420,8 @@ class NodeSurface(Node2D): | |||
| src = self._tsurface | |||
| ssize = src.get_size() | |||
| posx = self._offset[0] | |||
| posy = self._offset[1] | |||
| posx = self.position_x | |||
| posy = self.position_y | |||
| if self._alignCenter: | |||
| if dsize[0] > ssize[0]: | |||
| posx += (dsize[0] - ssize[0]) * 0.5 | |||
| @@ -443,6 +450,28 @@ class NodeSprite(Node2D): | |||
| } | |||
| @property | |||
| def image_width(self): | |||
| if self._NODESPRITE_DATA["surface"] is None: | |||
| return 0 | |||
| surf = self._NODESPRITE_DATA["surface"]() | |||
| return surf.get_width() | |||
| @property | |||
| def image_height(self): | |||
| if self._NODESPRITE_DATA["surface"] is None: | |||
| return 0 | |||
| surf = self._NODESPRITE_DATA["surface"]() | |||
| return surf.get_height() | |||
| @property | |||
| def sprite_width(self): | |||
| return int(self.rect_width * self.scale_x) | |||
| @property | |||
| def sprite_height(self): | |||
| return int(self.rect_height * self.scale_y) | |||
| @property | |||
| def rect(self): | |||
| return (self._NODESPRITE_DATA["rect"][0], | |||
| self._NODESPRITE_DATA["rect"][1], | |||
| @@ -461,7 +490,7 @@ class NodeSprite(Node2D): | |||
| self.rect_width = rect[2] | |||
| self.rect_height = rect[3] | |||
| except Exception as e: | |||
| raise e | |||
| raise e | |||
| @property | |||
| def rect_x(self): | |||
| @@ -471,6 +500,7 @@ class NodeSprite(Node2D): | |||
| if not isinstance(v, int): | |||
| raise TypeError("Expected integer value.") | |||
| self._NODESPRITE_DATA["rect"][0] = v | |||
| self._NODESPRITE_ValidateRect() | |||
| @property | |||
| def rect_y(self): | |||
| @@ -480,6 +510,7 @@ class NodeSprite(Node2D): | |||
| if not isinstance(v, int): | |||
| raise TypeError("Expected integer value.") | |||
| self._NODESPRITE_DATA["rect"][1] = v | |||
| self._NODESPRITE_ValidateRect() | |||
| @property | |||
| @@ -490,6 +521,7 @@ class NodeSprite(Node2D): | |||
| if not isinstance(v, int): | |||
| raise TypeError("Expected integer value.") | |||
| self._NODESPRITE_DATA["rect"][2] = v | |||
| self._NODESPRITE_ValidateRect() | |||
| @property | |||
| @@ -500,6 +532,7 @@ class NodeSprite(Node2D): | |||
| if not isinstance(v, int): | |||
| raise TypeError("Expected integer value.") | |||
| self._NODESPRITE_DATA["rect"][3] = v | |||
| self._NODESPRITE_ValidateRect() | |||
| @property | |||
| def center(self): | |||
| @@ -509,7 +542,8 @@ class NodeSprite(Node2D): | |||
| @property | |||
| def scale(self): | |||
| return (self._NODESPRITE_DATA["scale"][0], self._NODESPRITE_DATA["scale"][1]) | |||
| @scale.setter(self, scale): | |||
| @scale.setter | |||
| def scale(self, scale): | |||
| if not isinstance(scale, (list, tuple)): | |||
| raise TypeError("Expected a list or tuple.") | |||
| if len(scale) != 2: | |||
| @@ -528,6 +562,7 @@ class NodeSprite(Node2D): | |||
| if not isinstance(v, (int, float)): | |||
| raise TypeError("Expected number value.") | |||
| self._NODESPRITE_DATA["scale"][0] = float(v) | |||
| self._NODESPRITE_DATA["scale_dirty"] = True | |||
| @property | |||
| def scale_y(self): | |||
| @@ -537,12 +572,128 @@ class NodeSprite(Node2D): | |||
| if not isinstance(v, (int, float)): | |||
| raise TypeError("Expected number value.") | |||
| self._NODESPRITE_DATA["scale"][1] = float(v) | |||
| self._NODESPRITE_DATA["scale_dirty"] = True | |||
| @property | |||
| def image(self): | |||
| return self._NODESPRITE_DATA["image"] | |||
| @image.setter | |||
| def image(self, image): | |||
| def image(self, src): | |||
| src = src.strip() | |||
| if self._NODESPRITE_DATA["image"] == src: | |||
| return # Nothing to change... lol | |||
| if self._NODESPRITE_DATA["image"] != "": | |||
| self._NODESPRITE_DATA["surface"] = None # Clear reference to original surface. | |||
| pass | |||
| if src != "": | |||
| rm = self.resource | |||
| try: | |||
| if not rm.has("graphic", src): | |||
| rm.store("graphic", src) | |||
| self._NODESPRITE_DATA["image"] = src | |||
| self._NODESPRITE_DATA["surface"] = rm.get("graphic", src) | |||
| if self._NODESPRITE_DATA["surface"] is None: | |||
| self._NODESPRITE_DATA["image"] = "" | |||
| self._NODESPRITE_DATA["rect"]=[0,0,0,0] | |||
| else: | |||
| # Resetting the rect to identity for the new image. | |||
| surf = self._NODESPRITE_DATA["surface"]() | |||
| size = surf.get_size() | |||
| self._NODESPRITE_DATA["rect"]=[0,0,size[0], size[1]] | |||
| except Exception as e: | |||
| raise e | |||
| else: | |||
| self._NODESPRITE_DATA["image"] = "" | |||
| self._NODESPRITE_DATA["rect"]=[0,0,0,0] | |||
| def _render(self, surface): | |||
| # Call the on_render() method, if any | |||
| Node2D._callOnRender(self, surface) | |||
| # Paint the sprite onto the surface | |||
| if self._NODESPRITE_DATA["surface"] is not None: | |||
| rect = self._NODESPRITE_DATA["rect"] | |||
| scale = self._NODESPRITE_DATA["scale"] | |||
| surf = self._NODESPRITE_DATA["surface"]() | |||
| # Of course, only bother if we have a surface to work with. | |||
| if surf is not None: | |||
| # Do some prescaling work, if needed. | |||
| if self._NODESPRITE_DATA["scale_dirty"]: | |||
| self._NODESPRITE_UpdateScaleSurface(scale, surf) | |||
| fsurf = surf # Initial assumption that the surface is also the "frame" | |||
| # If we have a "frame" surface, however, let's get it and blit the rect into the frame surface. | |||
| if "frame_surf" in self._NODESPRITE_DATA: | |||
| fsurf = self._NODESPRITE_DATA["frame_surf"] | |||
| fsurf.blit(surf, (0, 0), rect) | |||
| # If scaling, then transform (scale) the frame surface into the scale surface and set the frame surface to the scale surface. | |||
| if "scale_surf" in self._NODESPRITE_DATA: | |||
| ssurf = self._NODESPRITE_DATA["scale_surf"] | |||
| pygame.transform.scale(fsurf, ssurf.get_size(), ssurf) | |||
| fsurf = ssurf | |||
| # Place the sprite! WHEEEEE! | |||
| pos = self.position | |||
| surface.blit(fsurf, pos) | |||
| # Call on all children | |||
| Node._render(self, surface) | |||
| def _NODESPRITE_UpdateScaleSurface(self, scale, surf): | |||
| self._NODESPRITE_DATA["scale_dirty"] = False | |||
| ssurf = None | |||
| if "scale_surf" in self._NODESPRITE_DATA: | |||
| ssurf = self._NODESPRITE_DATA["scale_surf"] | |||
| if scale[0] == 1.0 and scale[1] == 1.0: | |||
| if ssurf is not None: | |||
| del self._NODESPRITE_DATA["scale_surf"] | |||
| return | |||
| nw = int(self.rect_width * scale[0]) | |||
| nh = int(self.rect_height * scale[1]) | |||
| if nw != ssurf.get_width() or nh != ssurf.get_height(): | |||
| ssurf = pygame.Surface((nw, nh), pygame.SRCALPHA, surf) | |||
| ssurf.fill(pygame.Color(0,0,0,0)) | |||
| self._NODESPRITE_DATA["scale_surf"] = ssurf | |||
| def _NODESPRITE_ValidateRect(self): | |||
| if self._NODESPRITE_DATA["surface"] is None: | |||
| self._NODESPRITE_DATA["rect"] = [0,0,0,0] | |||
| else: | |||
| rect = self._NODESPRITE_DATA["rect"] | |||
| isize = (self.image_width, self.image_height) | |||
| if rect[0] < 0: | |||
| rect[2] += rect[0] | |||
| rect[0] = 0 | |||
| elif rect[0] >= isize[0]: | |||
| rect[0] = isize[0]-1 | |||
| rect[2] = 0 | |||
| if rect[1] < 0: | |||
| rect[3] += rect[1] | |||
| rect[1] = 0 | |||
| elif rect[1] >= isize[1]: | |||
| rect[1] = isize[1]-1 | |||
| rect[3] = 0 | |||
| if rect[2] < 0: | |||
| rect[2] = 0 | |||
| elif rect[0] + rect[2] > isize[0]: | |||
| rect[2] = isize[0] - rect[0] | |||
| if rect[3] < 0: | |||
| rect[3] = 0 | |||
| elif rect[1] + rect[3] > isize[1]: | |||
| rect[3] = isize[1] - rect[1] | |||
| fssize = [0,0] | |||
| if rect[2] > 0 and rect[3] > 0: | |||
| if rect[2] < isize[0] or rect[1] < isize[1]: | |||
| surf = self._NODESPRITE_DATA["surface"]() | |||
| self._NODESPRITE_DATA["frame_surf"] = pygame.Surface((rect[2], rect[3]), pygame.SRCALPHA, surf) | |||
| if fssize[0] > 0 and fssize[1] > 0: | |||
| pass | |||
| elif "frame_surf" in self._NODESPRITE_DATA: | |||
| del self._NODESPRITE_DATA["frame_surf"] | |||