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, )
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
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))
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