Example #1
0
    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))
Example #2
0
    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))
Example #4
0
    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)
Example #5
0
    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)
Example #6
0
    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)
Example #7
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()
Example #8
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))
Example #9
0
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