Example #1
0
    def initialize_grid(self):
        """
        Step through all of the calculations to determine the grid size and led size.

        :return: None
        """

        # Store Grid Size
        self.grid_size = Vector2(config.get("GRID_SIZE"))
        if self.draw_borders:
            self.perimeter_border_size = Vector2(
                config.get("PERIMETER_BORDER_SIZE"))
        else:
            self.perimeter_border_size = Vector2(0, 0)

        # Calculate cell_size
        self.calculate_cell_size(self.max_grid_pixel_size())

        # Create Background
        self.create_background()

        # Calculate LED Size
        self.calculate_led_size()

        log.info("LED size calculated %s, with borders %s", self.led_size,
                 self.cell_size)

        # store led rects, of just the LED rect
        self.led_rects = [[None for x in range(int(self.grid_size.y))]
                          for y in range(int(self.grid_size.x))]
        # each grid cells rect, includes led borders
        self.grid_rects = [[None for x in range(int(self.grid_size.y))]
                           for y in range(int(self.grid_size.x))]

        for x in range(int(self.grid_size.x)):
            for y in range(int(self.grid_size.y)):

                top = self.grid_background_position.y + (self.cell_size.y * y)
                left = self.grid_background_position.x + (self.cell_size.x * x)
                top += self.border_size.y
                left += self.border_size.x
                top += self.perimeter_border_size.y
                left += self.perimeter_border_size.x

                width = self.cell_size.x - (self.border_size.x * 2)
                height = self.cell_size.y - (self.border_size.y * 2)

                rect = pygame.Rect(left, top, width, height)
                self.led_rects[x][y] = rect

                top = self.grid_background_position.y + (
                    self.cell_size.y * y) + self.perimeter_border_size.y
                left = self.grid_background_position.x + (
                    self.cell_size.x * x) + self.perimeter_border_size.x

                width = self.cell_size.x
                height = self.cell_size.y

                rect = Rect(left, top, width, height)
                self.grid_rects[x][y] = rect
Example #2
0
    def __init__(self):
        """
        Manage the widgets layout.
        :return:
        """

        # Widgets are automatically sized by its parent panel(widget).  self.requested_size can influence that
        # automatic sizing.
        self.requested_size = Vector2(0, 0)

        # The size of the drawable widget. Does not include margins.
        self.size = Vector2(0, 0)
        # Offset of this widgets location within it's parents panel(widget) surface.
        # Does not include its own margins. use self.total_offset to include margins
        self.offset = Vector2(0, 0)
        # pygame.Rect, ( total_offset.x, total_offset.y, size.x, size.y)
        self.rect = Rect(0, 0, 0, 0)
        # base global_offset of the widget in screen space. would still need to add this widgets total_offset to get
        # correct screen space.
        self.base_global_offset = Vector2(0, 0)
        # pygame.Rect, with global_offset + total_offset for position, and self.size for width, height.
        self.global_rect = Rect(0, 0, 0, 0)
        # Information about the styles margins.
        self.margin = Margin()
        # data used during fit, which can be set by parent panel(widget). Useful so parent panel doesn't have to have
        # its own way of storing information about the widget for automatic layout. Such as grid x, y position.
        self.data = {}
Example #3
0
    def calculate_led_size(self):
        """
        Calculate the led size for each cell.

        :return: None
        """

        if self.draw_borders:
            self.border_size = Vector2(config.get("BORDER_SIZE"))
        else:
            self.border_size = Vector2(0, 0)

        width = self.cell_size.x - (self.border_size.x * 2)
        height = self.cell_size.y - (self.border_size.y * 2)

        self.led_size = vector2_to_floor(Vector2(width, height))

        self.led_surface = pygame.Surface(self.led_size)

        # Check that the LED size is at least 1px
        if self.led_size.x <= 1.0 or self.led_size.y <= 1.0:
            log.error(
                "LED border size is to large for calculated LED size '(%s, %s) pixels'",
                self.cell_size.x, self.cell_size.y)
            raise Exception("LED border size is to large.")
Example #4
0
    def create_background(self):
        """
        Calculates the background size and position, and creates the surface.

        :return: None
        """

        # Initial background Size
        background_size_px = Vector2(self.grid_size.x * self.cell_size.x,
                                     self.grid_size.y * self.cell_size.y)
        # add in perimeter border size

        background_size_px.x += (self.perimeter_border_size.x * 2)
        background_size_px.y += (self.perimeter_border_size.y * 2)

        self.grid_background_surface = pygame.Surface(
            vector2_to_int(background_size_px))

        if self.draw_borders > 0:
            color = config.get("DRAW_BORDERS_COLORS")[self.draw_borders - 1]
            self.grid_background_surface.fill(color)

        grid_background_position_rect = self.grid_background_surface.get_rect()
        grid_background_position_rect.centerx = self.layout.size.x / 2
        grid_background_position_rect.centery = self.layout.size.y / 2

        # Center the grid background in its space
        self.grid_background_position = Vector2(
            grid_background_position_rect.topleft)
    def confirm_customer_size(pixel_mapping):

        rows = len(pixel_mapping)
        if rows != int(Vector2(config.get("GRID_SIZE")).y):
            raise Exception(
                "Custom PIXEL_MAPPING rows '{}' does not match GRID_SIZE.y '{}'"
                .format(rows, int(Vector2(config.get("GRID_SIZE")).y)))

        columns = []
        for y in range(len(pixel_mapping)):
            x = len(pixel_mapping[y])
            if x not in columns:
                columns.append(x)

        if len(columns) != 1:
            raise Exception(
                "Custom PIXEL_MAPPING columns malformed, all are not of equal length."
            )

        if columns[0] != int(Vector2(config.get("GRID_SIZE")).x):
            raise Exception(
                "Custom PIXEL_MAPPING columns '{}' does not match GRID_SIZE.x '{}'"
                .format(columns[0], int(Vector2(config.get("GRID_SIZE")).x)))

        return columns[0], rows
Example #6
0
    def calculate_cell_size(self, max_grid_pixel_size):
        """
        Given the max grid pixel size, determine the size of the individual grid cells.

        :param max_grid_pixel_size: pygame.math.Vector2 of the max size of the whole grid.
        :return: None
        """

        width = max_grid_pixel_size.x / float(self.grid_size.x)
        height = max_grid_pixel_size.y / float(self.grid_size.y)

        # Check that the LED size is at least 1px
        if width <= 1.0 or height <= 1.0:
            log.error(
                "Calculated LED cell size less than 1 pixel.  The WINDOW_SIZE is to small to fit "
                "the configured GRID_SIZE")
            raise Exception("LED size less than 1 pixel")

        # Sqaure up the LED
        if config.get("SQUARE_LED"):
            if width < height:
                height = width
            else:
                width = height

        self.cell_size = vector2_to_floor(Vector2(width, height))
    def on_mousebuttondown(self, sender, event):

        global_rect = self.dotgrid.layout.global_rect

        if global_rect.collidepoint(event.pos):
            grid_size = self.dotgrid.grid_size
            grid_rects = self.dotgrid.grid_rects
            pos = Vector2(event.pos) - Vector2(global_rect.topleft)
            for x in range(int(grid_size.x)):
                for y in range(int(grid_size.y)):
                    if grid_rects[x][y].collidepoint(pos):
                        if self.selected and self.x == x and self.y == y:
                            self.clear()
                        else:
                            # self.clear()
                            self.set(x, y)
    def __init__(self):
        """
        Data model of a strip of LED's and also handles processes received data packets.

        :return:
        """
        self.grid_size = Vector2(config.get("GRID_SIZE"))

        # self.pixel_count = int(self.grid_size.x * self.grid_size.y)
        self.pixel_count = globals.mapping_data.pixel_count

        # setup initial pixel data
        size = self.pixel_count * 4
        self.data = bytearray(size)
        self.clear_data()

        self.spi_index = 0  # current pixel index of the spi_in function

        self.updated = None  # datetime of last time start frame was received
        self.packet_length = 0  # count of number of individual bytes received since last start frame was received.

        self._dirty = True  # keep track if data has been changed since last update call

        # cache blinker signals
        self._signal_startrecv = blinker.signal("stripdata.startrecv")
        self._signal_updated = blinker.signal("stripdata.updated")

        self.header_bytes_found = 0
        self.buffer_count = 0
        self.buffer = bytearray((0xFF, 0xFF, 0xFF, 0xFF))
    def __init__(self):
        """
        Widget to show information about the running screen.

        :return:
        """
        super(RunningInfo, self).__init__(x=145)
        self.layout.margin.set(0, 5, 10, 5)

        # LED information widgets
        self.led_grid_position_txt = []  # value of grid position
        self.led_strip_index_txt = []  # value of strip index
        self.led_value_txt = []  # value of strip index color
        self.led_color = []  # widget to show color block of strip index color

        row_size = 14
        left = SizedRows(row_size)
        right = SizedRows(row_size)
        self.set_left(left)
        self.set_right(right)

        left.set(self.hd_txt("Information"), 0)

        i = 1
        left.set(self.lbl_text("Emulator FPS:"), i)
        self.emulator_fps_txt = self.val_text("")
        right.set(self.emulator_fps_txt, i)

        i += 1
        left.set(self.lbl_text("Grid size:"), i)
        grid_size = Vector2(config.get("GRID_SIZE"))
        pixel_count = globals.mapping_data.pixel_count
        self.grid_size_txt = self.val_text("({:.0f}, {:.0f}), {:.0f}".format(grid_size.x, grid_size.y, pixel_count))
        right.set(self.grid_size_txt, i)

        i += 1
        left.set(self.lbl_text("Packet Updated:"), i)
        self.packet_updated_txt = self.val_text("")
        right.set(self.packet_updated_txt, i)

        i += 1
        left.set(self.lbl_text("Packet length:"), i)
        self.packet_length_txt = self.val_text("")
        right.set(self.packet_length_txt, i)

        i += 1
        left.set(self.lbl_text("Packet Rate:"), i)
        self.packet_rate = self.val_text("")
        right.set(self.packet_rate, i)

        i += 2
        self.pixel_info_count = 4
        self.create_pixel_info(left, right, i)

        blinker.signal("dotgrid.select.set").connect(self.on_dotgrid_select_set)
        blinker.signal("stripdata.updated").connect(self.on_data_updated)
        blinker.signal("ratecounter.updated").connect(self.on_ratecounter_updated)
Example #10
0
    def widthheight(self):
        """
        Return a Vector2 class of the total combined margins for width and height.
        width is left + right margins.
        height is top + bottom margins.

        :return: 'class pygame.math.Vector2' Vector2(width, height)
        """

        return Vector2(self.left + self.right, self.top + self.bottom)
Example #11
0
    def max_grid_pixel_size(self):
        """
        Calculate the max grid size in pixels.  Takes into account the layout of the right panel.
        :return: Vector2, max grid size in pixels
        """

        max_width = self.layout.rect.width - (self.perimeter_border_size.x * 2)
        max_height = self.layout.rect.height - (self.perimeter_border_size.y *
                                                2)

        return Vector2(max_width, max_height)
    def __init__(self):
        """
        Provide the mapping from a single series strip of DotStar pixels to an x, y grid

        :return:
        """

        self.grid_size = Vector2(config.get("GRID_SIZE"))
        self.pixel_count = 0

        self.data = [[None for x in range(int(self.grid_size.y))]
                     for y in range(int(self.grid_size.x))]

        pixel_mapping = config.get("PIXEL_MAPPING")
        if pixel_mapping is not None:
            self.custom_mapping(pixel_mapping)
        else:
            self.prebuilt_mappings()
            self.pixel_count = int(self.grid_size.x * self.grid_size.y)
Example #13
0
    def __init__(self):
        super(AboutScene, self).__init__()

        two_rows = panels.TwoRows(-50)
        self.set_panel(two_rows)

        top = self.text_panel()

        two_rows.set_top(top)

        bottom = panels.CenterSingle()
        two_rows.set_bottom(bottom)

        button = ButtonWidget("[F1] Return", key=pygame.K_F1)
        button.layout.requested_size = Vector2(100, 21)
        bottom.set(button)
        blinker.signal("gui.button.pressed").connect(self.on_return,
                                                     sender=button)

        self.fit()
Example #14
0
    def text_panel():
        panel = panels.CenterSingle(25)

        rows_panel = panels.SizedRows(18, use_surface=True, color=(40, 40, 40))
        rows_panel.layout.requested_size = Vector2(500, 400)
        panel.set(rows_panel)

        filename = os.path.join(MEDIA_PATH, 'about.txt')
        with open(filename, 'r') as f:
            text = f.read()

        text_split = text.split("\n")

        widget = TextLabelWidget(config.get("WINDOW_CAPTION"), 18,
                                 config.get("BRAND_TITLE"))
        widget.layout.margin.set(0, 0, 0, 5)
        rows_panel.set(widget, 0)

        for i, line in enumerate(text_split):
            widget = TextLabelWidget(line, 12, (255, 255, 255))
            widget.layout.margin.set(0, 0, 0, 5)
            rows_panel.set(widget, i + 2)

        return panel
Example #15
0
 def topleft(self):
     """
     Return a Vector2 class of the top left corner margins
     :return: 'class pygame.math.Vector2' Vector2(left, top)
     """
     return Vector2(self.left, self.top)
Example #16
0
    def set_size(self, possible_size, offset, global_offset, flags):
        """
        Automatically calculate the widgets size and position.  Size will never exceed possible_size, but may be
        smaller depending on flags.  The calculation is also influenced by the widgets self.requested_size

        FILLX
        FILLY
        CENTERX
        CENTERY

        :param possible_size: Vector2 of the maximum size the parent panel(widget) has allotted this widget.
        :param offset:  Vector2 top left corner of where this widget will draw n the parent's surface
        :param global_offset: total screen global offset of where offset is actually located. This is needed for
                              to maintain screen space rect's of this widget. useful for mouse clicks..
        :param flags: Positioning flags to influence the automatic fitting.
        :return: None
        """

        # Store base global_offset
        self.base_global_offset = global_offset
        # Store base offset
        self.offset = offset

        size = Vector2(0, 0)

        if flags & FILLX:
            if self.requested_size.x == 0 or self.requested_size.x == -1:
                size.x = possible_size.x
            else:
                raise Exception(
                    "can not FILLX, as widget.style.x is already set")
        else:
            if self.requested_size.x == 0:
                raise Exception("widget.style.x is equal to 0")
            elif self.requested_size.x == -1:
                # even if FILLX wasn't set by parent, fill out to parents possible_size
                size.x = possible_size.x
            else:
                size.x = self.requested_size.x

        if flags & FILLY:
            if self.requested_size.y == 0 or self.requested_size.y == -1:
                size.y = possible_size.y
            else:
                raise Exception(
                    "can not FILLY, as widget.style.y is already set")
        else:
            if self.requested_size.y == 0:
                raise Exception("widget.style.y is equal to 0")
            elif self.requested_size.y == -1:
                # even if FILLY wasn't set by parent, fill out to parents possible_size
                size.y = possible_size.y
            else:
                size.y = self.requested_size.y

        # because size is the size of the widget's drawable surface, remove its own margins.
        size -= self.margin.widthheight
        self.size = size

        # Once widgets size has been determined, we can center it within its parents space by adjusting the margins.
        # TODO this will not work if the widgets are ever re-sized, as the margins are used to calculate the size in the
        # step just above this.
        if flags & CENTERX:
            space = possible_size.x - size.x
            self.margin.left = space / 2.0
            self.margin.right = space / 2.0
        if flags & CENTERY:
            space = possible_size.y - size.y
            self.margin.top = space / 2.0
            self.margin.bottom = space / 2.0

        # Cache Rectangle, topleft is offset + margin, size is size of drawable widget surface.
        self.rect = Rect(self.total_offset, self.size)

        # Cache Global Rect. Same as above but globally positioned. Useful for mouse events
        self.global_rect = Rect(self.base_global_offset + self.total_offset,
                                self.size)