| from .display import Display | from .display import Display | ||||
| from .events import Events | from .events import Events | ||||
| from .resource import Manager | |||||
| from .resource import ResourceManager | |||||
| import pygame | import pygame | ||||
| self._NODE_DATA={ | self._NODE_DATA={ | ||||
| "parent":None, | "parent":None, | ||||
| "name":name, | "name":name, | ||||
| "children":[] | |||||
| "children":[], | |||||
| "resource":None | "resource":None | ||||
| } | } | ||||
| if parent is not None: | if parent is not None: | ||||
| Node.__init__(self, name, parent) | Node.__init__(self, name, parent) | ||||
| except NodeError as e: | except NodeError as e: | ||||
| raise 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"): | if hasattr(self, "on_render"): | ||||
| self._ACTIVE_SURF = surface | self._ACTIVE_SURF = surface | ||||
| self.on_render() | self.on_render() | ||||
| del self._ACTIVE_SURF | 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): | def draw_image(self, img, pos=(0,0), rect=None): | ||||
| if not hasattr(self, "_ACTIVE_SURF"): | if not hasattr(self, "_ACTIVE_SURF"): | ||||
| return | return | ||||
| except NodeError as e: | except NodeError as e: | ||||
| raise e | raise e | ||||
| # TODO: Update this class to use the _NODE*_DATA={} structure. | # TODO: Update this class to use the _NODE*_DATA={} structure. | ||||
| self._offset = (0.0, 0.0) | |||||
| self._scale = (1.0, 1.0) | self._scale = (1.0, 1.0) | ||||
| self._scaleToDisplay = False | self._scaleToDisplay = False | ||||
| self._scaleDirty = False | self._scaleDirty = False | ||||
| @property | @property | ||||
| def height(self): | 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 | @property | ||||
| def scale(self): | def scale(self): | ||||
| src = self._tsurface | src = self._tsurface | ||||
| ssize = src.get_size() | ssize = src.get_size() | ||||
| posx = self._offset[0] | |||||
| posy = self._offset[1] | |||||
| posx = self.position_x | |||||
| posy = self.position_y | |||||
| if self._alignCenter: | if self._alignCenter: | ||||
| if dsize[0] > ssize[0]: | if dsize[0] > ssize[0]: | ||||
| posx += (dsize[0] - ssize[0]) * 0.5 | posx += (dsize[0] - ssize[0]) * 0.5 | ||||
| } | } | ||||
| @property | @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): | def rect(self): | ||||
| return (self._NODESPRITE_DATA["rect"][0], | return (self._NODESPRITE_DATA["rect"][0], | ||||
| self._NODESPRITE_DATA["rect"][1], | self._NODESPRITE_DATA["rect"][1], | ||||
| self.rect_width = rect[2] | self.rect_width = rect[2] | ||||
| self.rect_height = rect[3] | self.rect_height = rect[3] | ||||
| except Exception as e: | except Exception as e: | ||||
| raise e | |||||
| raise e | |||||
| @property | @property | ||||
| def rect_x(self): | def rect_x(self): | ||||
| if not isinstance(v, int): | if not isinstance(v, int): | ||||
| raise TypeError("Expected integer value.") | raise TypeError("Expected integer value.") | ||||
| self._NODESPRITE_DATA["rect"][0] = v | self._NODESPRITE_DATA["rect"][0] = v | ||||
| self._NODESPRITE_ValidateRect() | |||||
| @property | @property | ||||
| def rect_y(self): | def rect_y(self): | ||||
| if not isinstance(v, int): | if not isinstance(v, int): | ||||
| raise TypeError("Expected integer value.") | raise TypeError("Expected integer value.") | ||||
| self._NODESPRITE_DATA["rect"][1] = v | self._NODESPRITE_DATA["rect"][1] = v | ||||
| self._NODESPRITE_ValidateRect() | |||||
| @property | @property | ||||
| if not isinstance(v, int): | if not isinstance(v, int): | ||||
| raise TypeError("Expected integer value.") | raise TypeError("Expected integer value.") | ||||
| self._NODESPRITE_DATA["rect"][2] = v | self._NODESPRITE_DATA["rect"][2] = v | ||||
| self._NODESPRITE_ValidateRect() | |||||
| @property | @property | ||||
| if not isinstance(v, int): | if not isinstance(v, int): | ||||
| raise TypeError("Expected integer value.") | raise TypeError("Expected integer value.") | ||||
| self._NODESPRITE_DATA["rect"][3] = v | self._NODESPRITE_DATA["rect"][3] = v | ||||
| self._NODESPRITE_ValidateRect() | |||||
| @property | @property | ||||
| def center(self): | def center(self): | ||||
| @property | @property | ||||
| def scale(self): | def scale(self): | ||||
| return (self._NODESPRITE_DATA["scale"][0], self._NODESPRITE_DATA["scale"][1]) | 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)): | if not isinstance(scale, (list, tuple)): | ||||
| raise TypeError("Expected a list or tuple.") | raise TypeError("Expected a list or tuple.") | ||||
| if len(scale) != 2: | if len(scale) != 2: | ||||
| if not isinstance(v, (int, float)): | if not isinstance(v, (int, float)): | ||||
| raise TypeError("Expected number value.") | raise TypeError("Expected number value.") | ||||
| self._NODESPRITE_DATA["scale"][0] = float(v) | self._NODESPRITE_DATA["scale"][0] = float(v) | ||||
| self._NODESPRITE_DATA["scale_dirty"] = True | |||||
| @property | @property | ||||
| def scale_y(self): | def scale_y(self): | ||||
| if not isinstance(v, (int, float)): | if not isinstance(v, (int, float)): | ||||
| raise TypeError("Expected number value.") | raise TypeError("Expected number value.") | ||||
| self._NODESPRITE_DATA["scale"][1] = float(v) | self._NODESPRITE_DATA["scale"][1] = float(v) | ||||
| self._NODESPRITE_DATA["scale_dirty"] = True | |||||
| @property | @property | ||||
| def image(self): | def image(self): | ||||
| return self._NODESPRITE_DATA["image"] | return self._NODESPRITE_DATA["image"] | ||||
| @image.setter | @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"] != "": | if self._NODESPRITE_DATA["image"] != "": | ||||
| self._NODESPRITE_DATA["surface"] = None # Clear reference to original surface. | 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"] | |||||