Beispiel #1
0
    def edit_palette_ani(self, ani_pal_id):
        if not self.parent.dpla.has_for_palette(ani_pal_id):
            md = Gtk.MessageDialog(
                MainController.window(),
                Gtk.DialogFlags.DESTROY_WITH_PARENT,
                Gtk.MessageType.ERROR,
                Gtk.ButtonsType.OK,
                "Palette Animation is not enabled for this palette.",
                title="Warning!")
            md.set_position(Gtk.WindowPosition.CENTER)
            md.run()
            md.destroy()
            return
        # This is controlled by a separate controller
        dict_pals = OrderedDict()

        list_of_colors = self.parent.dpla.colors[ani_pal_id *
                                                 16:(ani_pal_id + 1) * 16]
        # We need to transpose the list to instead have a list of frames.
        list_of_frames = list(
            [] for _ in range(0, int(len(list_of_colors[0]) / 3)))
        for color in list_of_colors:
            for frame_idx, c in enumerate(chunks(color, 3)):
                list_of_frames[frame_idx] += c
        for i, pal in enumerate(list_of_frames):
            dict_pals[f'F{i + 1}'] = pal.copy()

        cntrl = PaletteEditorController(MainController.window(), dict_pals,
                                        False, True, False)
        edited_palettes = cntrl.show()
        if edited_palettes:
            # Transpose back
            edited_colors = list(
                [] for _ in range(0, int(len(edited_palettes[0]) / 3)))
            for palette in edited_palettes:
                for color_idx, c in enumerate(chunks(palette, 3)):
                    edited_colors[color_idx] += c

            self.parent.dpla.colors[ani_pal_id * 16:(ani_pal_id + 1) *
                                    16] = edited_colors
            self.parent.reload_all()
            self.parent.mark_as_modified()
        del cntrl
 def palette(self) -> bytes:
     data = bytearray(len(self._palette) // 3 * ICON_PAL_CNT // 2)
     cursor = 0
     for (r, g, b) in chunks(self._palette, 3):
         r //= 8
         g = (g // 8) << 5
         b = (b // 8) << 10
         write_u16(data, u16(r + g + b), cursor)
         cursor += 2
     return data
    def to_pil(self) -> Image.Image:
        tilemap = []
        for i in range(ICON_DIM_IMG_TILES * ICON_DIM_IMG_TILES):
            tilemap.append(
                TilemapEntry(idx=i, pal_idx=0, flip_x=False, flip_y=False))

        return to_pil(
            tilemap,
            list(chunks(self.bitmap, ICON_DIM_TILE * ICON_DIM_TILE // 2)),
            [self._palette],
            ICON_DIM_TILE,
            ICON_DIM_IMG_PX,
            ICON_DIM_IMG_PX,
            bpp=4,
        )
Beispiel #4
0
 def on_men_chunks_layer1_edit_activate(self):
     all_tilemaps = list(
         itertools.chain.from_iterable(self.parent.dpc.chunks))
     static_tiles_provider = DungeonTilesProvider(self.parent.dpci)
     palettes_provider = DungeonPalettesProvider(self.parent.dpl,
                                                 self.parent.dpla)
     cntrl = ChunkEditorController(MainController.window(), all_tilemaps,
                                   static_tiles_provider, palettes_provider,
                                   self.parent.pal_ani_durations)
     edited_mappings = cntrl.show()
     if edited_mappings:
         self.parent.dpc.chunks = list(
             chunks(edited_mappings, DPC_TILING_DIM * DPC_TILING_DIM))
         self.parent.reload_all()
         self.parent.mark_as_modified()
     del cntrl
Beispiel #5
0
 def _init_rules(self):
     def ia(i):
         return self.builder.get_object(f'rules_a{i}').get_active()
     self.rules = list(chunks([ia(i) for i in range(0, 9)], 3))
Beispiel #6
0
    def from_pil(self,
                 dpc: Dpc,
                 dpci: Dpci,
                 dpl: Dpl,
                 img: Image.Image,
                 force_import=False):
        """
        Import an entire background from an image.
        Changes all tiles, tile mappings and chunks in the DPC/DPCI and re-writes the mappings of the DBG.
        Imports the palettes of the image to the DPL.

        The passed PIL will be split into separate tiles and the tile's palette index in the tile mapping for this
        coordinate is determined by the first pixel value of each tile in the PIL. The PIL
        must have a palette containing up to 16 sub-palettes with 16 colors each (256 colors).

        If a pixel in a tile uses a color outside of it's 16 color range, an error is thrown or
        the color is replaced with 0 of the palette (transparent). This is controlled by
        the force_import flag.

        The input images must have the same dimensions as the DBG (same dimensions as to_pil_single_layer would export).
        """
        expected_width = DBG_TILING_DIM * DBG_WIDTH_AND_HEIGHT * DPCI_TILE_DIM
        expected_height = DBG_TILING_DIM * DBG_WIDTH_AND_HEIGHT * DPCI_TILE_DIM
        if img.width != expected_width:
            raise ValueError(
                f"Can not import map background: Width of image must match the expected width: "
                f"{expected_width}px")
        if img.height != expected_height:
            raise ValueError(
                f"Can not import map background: Height of image must match the expected height: "
                f"{expected_height}px")

        # Import tiles, tile mappings and chunks mappings
        tiles, all_possible_tile_mappings, palettes = from_pil(
            img, DPL_PAL_LEN, 16, DPCI_TILE_DIM, img.width, img.height, 3, 3,
            force_import)
        # Remove any extra colors
        palettes = palettes[:DPL_MAX_PAL]

        dpci.import_tiles(tiles)

        # Build a new list of chunks / tile mappings for the DPC based on repeating chunks
        # in the imported image. Generate chunk mappings.
        chunk_mappings = []
        chunk_mappings_counter = 1
        tile_mappings = []
        tiles_in_chunk = DBG_TILING_DIM * DBG_TILING_DIM
        for chk_fst_tile_idx in range(
                0,
                DBG_WIDTH_AND_HEIGHT * DBG_WIDTH_AND_HEIGHT * tiles_in_chunk,
                tiles_in_chunk):
            chunk = all_possible_tile_mappings[
                chk_fst_tile_idx:chk_fst_tile_idx + tiles_in_chunk]
            start_of_existing_chunk = search_for_chunk(chunk, tile_mappings)
            if start_of_existing_chunk is not None:
                chunk_mappings.append(
                    int(start_of_existing_chunk / tiles_in_chunk) + 1)
            else:
                tile_mappings += chunk
                chunk_mappings.append(chunk_mappings_counter)
                chunk_mappings_counter += 1

        dpc.import_tile_mappings(
            list(chunks(tile_mappings, DPC_TILING_DIM * DPC_TILING_DIM)))
        self.mappings = chunk_mappings

        # Import palettes
        dpl.palettes = palettes