def paintEvent(self, event): painter = QPainter(self) gc = GraphicContext(painter) for i in range(len(self.brushes)): x = i % self.get_columns() y = i // self.get_columns() cell_w = self.width() / self.get_columns() rect = Rectf(x * cell_w, y * self.cell_height, (x + 1) * cell_w, (y + 1) * self.cell_height) if (x + y - 1) % 2 == 0: gc.fill_rect(rect, Color(224, 224, 224)) else: gc.fill_rect(rect, Color(192, 192, 192)) sprite = self.brushes[i].get_sprite() sprite.set_alignment(Origin.center, 0, 0) sprite.set_scale(min(1.0, self.cell_width / sprite.width), min(1.0, self.cell_height / sprite.height)) sprite.draw(rect.left + rect.width / 2, rect.top + rect.height / 2, gc) # highlight the current selection if self.mouse_over_tile == i and self.has_focus: gc.fill_rect(rect, Color(0, 0, 255, 20))
def get_value(self): if self.kind == Item.KIND_LABEL: return None elif self.kind == Item.KIND_RADIO: idx = 0 for button in self.group.buttons(): if button == self.group.checkedButton(): return idx idx += 1 elif self.kind == Item.KIND_ENUM: return self.body.currentText() elif self.kind == Item.KIND_BOOL: return self.body.checkState() == Qt.Checked elif self.kind == Item.KIND_INT: return int(self.body.text()) elif self.kind == Item.KIND_FLOAT: return float(self.body.text()) elif self.kind == Item.KIND_STRING: return self.body.text() elif self.kind == Item.KIND_COLOR: # FIXME: not implemented return Color() else: assert False, "unknown item type: %r" % self.kind
def paintEvent(self, event): painter = QPainter(self) gc = GraphicContext(painter) brush = ToolContext.current.tile_brush start_row = event.rect().top() // self.cell_size end_row = (event.rect().bottom() + self.cell_size - 1) // self.cell_size end_index = min(end_row * self.columns, len(self.tiles)) # Draw tiles for i in range(start_row * self.columns, end_index): x = i % self.columns y = i // self.columns tile = self.tileset.create(self.tiles[i]) rect = Rect(Point(int(x * self.cell_size), int(y * self.cell_size)), Size(self.cell_size, self.cell_size)) if tile: sprite = tile.get_sprite() sprite.set_scale(self.scale, self.scale) sprite.draw(int(x * self.cell_size), int(y * self.cell_size), gc) # Use grid in the tileselector gc.draw_rect(rect, Color(0, 0, 0, 128)) # mark the currently selected tile if brush.width == 1 and brush.height == 1 and brush.at(0, 0) == self.tiles[i]: gc.fill_rect(rect, Color(0, 0, 255, 100)) elif self.mouse_over_tile == i and self.has_focus: gc.fill_rect(rect, Color(0, 0, 255, 20)) # draw rectangle selection if self.region_select: rect = self.get_selection() rect.top *= self.cell_size rect.bottom *= self.cell_size rect.left *= self.cell_size rect.right *= self.cell_size gc.fill_rect(rect, Color(0, 0, 255, 100))
def draw(self, gc, color=Color(255, 255, 255, 100)): tile_size = self.tilemap.get_tileset().get_tile_size() gc.fill_rect( Rect(self.selection.left * tile_size, self.selection.top * tile_size, self.selection.right * tile_size, self.selection.bottom * tile_size), color)
def draw(self, gc): if self.is_active: tilemap = ToolContext.current.tilemap_layer if not tilemap: return if self.shift_pressed: self.selection.draw(gc, Color(255, 128, 128, 100)) else: self.selection.draw(gc)
def __init__(self, tileset, w, h): super().__init__() self.name = "<no name>" self.tileset = tileset self.field = Field.from_size(w, h) self.background_color = Color(0, 0, 0, 0) self.foreground_color = Color(255, 255, 255, 255) # FIXME: Move this to the widget or to some more generic map-properties thingy self.draw_grid = False self.draw_attribute = False self.metadata = None # Do not touch! Use LayerSelector to hide/show layers. self.hidden = False for y in range(0, self.field.height): for x in range(0, self.field.width): self.field.put(x, y, 0)
def paintEvent(self, event): if not self.parent.get_workspace().get_map(): return if not self.parent or not self.parent.get_workspace(): return painter = QPainter(self) gc = GraphicContext(painter) gc.push_modelview() # FIXME: Do this only on map changes if self.last_serial != self.parent.get_workspace().get_map( ).get_serial(): # or editor_map != parent.get_workspace().get_map()) self.update_minimap() self.last_serial = self.parent.get_workspace().get_map( ).get_serial() self.editor_map = self.parent.get_workspace().get_map() if True: # Draw background color gc.fill_rect(Rect(Point(0, 0), Size(self.width(), self.height())), Color(200, 200, 200, 225)) # FIXME: This doesn't work all that well tilemap = ToolContext.current.tilemap_layer if tilemap and tilemap.height != 0 and tilemap.width != 0: tile_size = tilemap.get_tileset().get_tile_size() map_width = tilemap.width * tile_size map_height = tilemap.height * tile_size small_tile_size = Size(tile_size * self.width() / map_width + 1, tile_size * self.height() / map_height + 1) field = tilemap.field # FIXME: No current tileset if False: for y in range(0, field.height): for x in range(0, field.width): tile = tilemap.get_tileset().create(field.at(x, y)) if tile: gc.fill_rect( Rect( Point((x * tile_size) * self.width() / map_width, (y * tile_size) * self.height() / map_height), small_tile_size), tile.get_color()) if self.minimap_surface: self.minimap_surface.draw( Rect(Point(0, 0), Size(self.width(), self.height()))) # Draw cursor rect = self.parent.get_clip_rect() screen_rect = Rect( Point(rect.left * self.width() / map_width, rect.top * self.height() / map_height), Size(rect.width * self.width() / map_width, rect.height * self.height() / map_height)) gc.fill_rect(screen_rect, Color(255, 255, 0, 50)) gc.draw_rect(screen_rect, Color(0, 0, 0)) gc.pop_modelview()
def draw(self, gc, pos=Point()): if self.hidden: return tile_size = self.tileset.get_tile_size() if False and self.background_color.get_alpha() != 0: gc.fill_rect(Rect(pos, Size(self.field.width * tile_size, self.field.height * tile_size)), self.background_color) # The visible rectangle rect = Rect(gc.get_clip_rect()) # max() here stops tiles off screen (below 0) from being drawn start_x = max(0, pos.x // tile_size) start_y = max(0, pos.y // tile_size) # min() here stops tiles off screen (above size of clip rect) from being drawn end_x = min(self.field.width + pos.x // tile_size, rect.right // tile_size + 1) end_y = min(self.field.height + pos.y // tile_size, rect.bottom // tile_size + 1) if self.foreground_color != Color(255, 255, 255, 255): for y in range(start_y, end_y): for x in range(start_x, end_x): # The coordinates on the field are from 0 - field.width tile_id = self.field.at(x - start_x, y - start_y) if tile_id: tile = self.tileset.create(tile_id) if tile: # skip transparent tile for faster draw sprite = tile.get_sprite() sprite.set_color(self.foreground_color) sprite.draw(x * tile_size, y * tile_size, gc) if self.draw_attribute: gc.fill_rect(Rect(Point(x, y), Size(self.tileset.get_tile_size(), self.tileset.get_tile_size())), tile.get_attribute_color()) else: for y in range(start_y, end_y): for x in range(start_x, end_x): tile_id = self.field.at(x - start_x, y - start_y) if tile_id: # skip transparent tile for faster draw tile = self.tileset.create(self.field.at(x - start_x, y - start_y)) if tile: tile.get_sprite().draw(x * tile_size, y * tile_size, gc) if self.draw_attribute: gc.fill_rect(Rect(Point(x, y), Size(self.tileset.get_tile_size(), self.tileset.get_tile_size())), tile.get_attribute_color()) if self.draw_grid: for y in range(start_y, end_y): gc.draw_line(start_x * tile_size, y * tile_size, end_x * tile_size, y * tile_size, Color(150, 150, 150)) for x in range(start_x, end_x): gc.draw_line(x * tile_size, start_y * tile_size, x * tile_size, end_y * tile_size, Color(150, 150, 150))
class TilemapLayer(Layer): def __init__(self, tileset, w, h): super().__init__() self.name = "<no name>" self.tileset = tileset self.field = Field.from_size(w, h) self.background_color = Color(0, 0, 0, 0) self.foreground_color = Color(255, 255, 255, 255) # FIXME: Move this to the widget or to some more generic map-properties thingy self.draw_grid = False self.draw_attribute = False self.metadata = None # Do not touch! Use LayerSelector to hide/show layers. self.hidden = False for y in range(0, self.field.height): for x in range(0, self.field.width): self.field.put(x, y, 0) def draw(self, gc, pos=Point()): if self.hidden: return tile_size = self.tileset.get_tile_size() if False and self.background_color.get_alpha() != 0: gc.fill_rect(Rect(pos, Size(self.field.width * tile_size, self.field.height * tile_size)), self.background_color) # The visible rectangle rect = Rect(gc.get_clip_rect()) # max() here stops tiles off screen (below 0) from being drawn start_x = max(0, pos.x // tile_size) start_y = max(0, pos.y // tile_size) # min() here stops tiles off screen (above size of clip rect) from being drawn end_x = min(self.field.width + pos.x // tile_size, rect.right // tile_size + 1) end_y = min(self.field.height + pos.y // tile_size, rect.bottom // tile_size + 1) if self.foreground_color != Color(255, 255, 255, 255): for y in range(start_y, end_y): for x in range(start_x, end_x): # The coordinates on the field are from 0 - field.width tile_id = self.field.at(x - start_x, y - start_y) if tile_id: tile = self.tileset.create(tile_id) if tile: # skip transparent tile for faster draw sprite = tile.get_sprite() sprite.set_color(self.foreground_color) sprite.draw(x * tile_size, y * tile_size, gc) if self.draw_attribute: gc.fill_rect(Rect(Point(x, y), Size(self.tileset.get_tile_size(), self.tileset.get_tile_size())), tile.get_attribute_color()) else: for y in range(start_y, end_y): for x in range(start_x, end_x): tile_id = self.field.at(x - start_x, y - start_y) if tile_id: # skip transparent tile for faster draw tile = self.tileset.create(self.field.at(x - start_x, y - start_y)) if tile: tile.get_sprite().draw(x * tile_size, y * tile_size, gc) if self.draw_attribute: gc.fill_rect(Rect(Point(x, y), Size(self.tileset.get_tile_size(), self.tileset.get_tile_size())), tile.get_attribute_color()) if self.draw_grid: for y in range(start_y, end_y): gc.draw_line(start_x * tile_size, y * tile_size, end_x * tile_size, y * tile_size, Color(150, 150, 150)) for x in range(start_x, end_x): gc.draw_line(x * tile_size, start_y * tile_size, x * tile_size, end_y * tile_size, Color(150, 150, 150)) def get_tile(self, x, y): if 0 <= x < self.field.width and 0 <= y < self.field.height: return self.field.at(x, y) else: return 0 def resize(self, size, point): self.field.resize(size.width, size.height, point.x, point.y) def replace_tile(self, source_id, replacement_id): for y in range(self.field.height): for x in range(self.field.width): if self.field.at(x, y) == source_id: self.field.put(x, y, replacement_id) def flood_fill_at(self, pos, brush): replace_id = self.field.at(pos.x, pos.y) if replace_id not in brush.field: self._flood_fill_at(pos.x, pos.y, brush, replace_id) def _flood_fill_at(self, orig_x, orig_y, brush, replace_id): stack = [(orig_x, orig_y)] def add(x, y): if 0 <= x < self.field.width and 0 <= y < self.field.height: stack.append((x, y)) while stack: x, y = stack.pop() tile_id = self.field.at(x, y) if tile_id == replace_id: fill_id = brush.at((x - orig_x) % brush.width, (y - orig_y) % brush.height) self.field.put(x, y, fill_id) add(x + 1, y) add(x - 1, y) add(x, y + 1) add(x, y - 1) def draw_tile(self, tile_id, pos): assert isinstance(tile_id, int) if 0 <= pos.x < self.field.width and 0 <= pos.y < self.field.height: self.field.put(pos.x, pos.y, tile_id) # formerly draw_tile() def draw_tile_brush(self, brush, pos): self.draw_tiles(self.field, brush, pos) @staticmethod def draw_tiles(field, brush, pos): start_x = max(0, -pos.x) start_y = max(0, -pos.y) end_x = min(brush.width, field.width - pos.x) end_y = min(brush.height, field.height - pos.y) for y in range(start_y, end_y): for x in range(start_x, end_x): if brush.is_opaque() or brush.at(x, y) != 0: field.put(pos.x + x, pos.y + y, brush.at(x, y)) def set_draw_attribute(self, t): self.draw_attribute = t def get_draw_attribute(self): return self.draw_attribute def set_draw_grid(self, t): self.draw_grid = t def get_draw_grid(self): return self.draw_grid def create_pixelbuffer(self): tile_size = self.tileset.get_tile_size() pixelbuffer = PixelBuffer(self.width * tile_size, self.height * tile_size) pixelbuffer.lock() buf = pixelbuffer.get_data() width = pixelbuffer.width height = pixelbuffer.height # Draw a nice gradient for y in range(height): for x in range(width): buf[4 * (y * width + x) + 0] = 255 buf[4 * (y * width + x) + 1] = 255 buf[4 * (y * width + x) + 2] = 255 * y // height buf[4 * (y * width + x) + 3] = 255 * y // height pixelbuffer.unlock() for y in range(self.height): for x in range(self.width): tile = self.tileset.create(self.field.at(x, y)) if tile: buf = tile.get_pixelbuffer() if buf: blit(pixelbuffer, buf, x * tile_size, y * tile_size) return pixelbuffer def get_bounding_rect(self): return Rect(Point(0, 0), Size(self.field.width * self.tileset.get_tile_size(), self.field.height * self.tileset.get_tile_size())) def world2tile(self, pos): x = int(pos.x / self.tileset.get_tile_size()) y = int(pos.y / self.tileset.get_tile_size()) return Point(x - 1 if (pos.x < 0) else x, y - 1 if (pos.y < 0) else y) def get_tileset(self): return self.tileset def get_data(self): return list(self.field._data.flatten()) def set_data(self, data: List[int]): self.field = Field.from_list(self.field.width, self.field.height, data) def set_background_color(self, color): self.background_color = color def set_foreground_color(self, color): self.foreground_color = color @property def width(self): return self.field.width @property def height(self): return self.field.height def has_bounding_rect(self): return True