예제 #1
0
 def _change_map_bg(self, level_id: int, draw, drawer):
     if level_id!=-1:
         bma = self.map_bg_module.get_bma(self._get_map_id(level_id))
         bpl = self.map_bg_module.get_bpl(self._get_map_id(level_id))
         bpc = self.map_bg_module.get_bpc(self._get_map_id(level_id))
         bpas = self.map_bg_module.get_bpas(self._get_map_id(level_id))
         surface = pil_to_cairo_surface(
             bma.to_pil(bpc, bpl, bpas, False, False, single_frame=True)[0].convert('RGBA')
         )
         if drawer:
             if level_id == WORLD_MAP_DEFAULT_ID:
                 draw.set_size_request(504 * SCALE, 336 * SCALE)
             else:
                 bma_width = bma.map_width_camera * BPC_TILE_DIM
                 bma_height = bma.map_height_camera * BPC_TILE_DIM
                 draw.set_size_request(
                     bma_width * SCALE, bma_height * SCALE
                 )
             drawer.level_id = level_id
             drawer.map_bg = surface
             draw.queue_draw()
     else:
         surface = pil_to_cairo_surface(
             Image.new(mode="RGBA", size=(1,1), color=(0,0,0,0))
         )
         drawer.level_id = -1
         drawer.map_bg = surface
         draw.set_size_request(1,1)
         draw.queue_draw()
예제 #2
0
 def __init__(self, zmappa: ZMappaT):
     self._tiles = []
     base = zmappa.to_pil_tiles_minimized(ZMappaTVariation.OPAQUE).convert('RGBA')
     for y in range(0, 4):
         for x in range(0, ZMAPPAT_NB_TILES_PER_LINE // 2):
             self._tiles.append(pil_to_cairo_surface(base.crop(
                 (x * ZMAPPAT_DIM, y * ZMAPPAT_DIM, (x + 1) * ZMAPPAT_DIM, (y + 1) * ZMAPPAT_DIM)
             )))
     self._secondary = pil_to_cairo_surface(Image.open(os.path.join(data_dir(), 'minimap_secondary.png')))
     self._buried = pil_to_cairo_surface(Image.open(os.path.join(data_dir(), 'minimap_buried.png')))
예제 #3
0
 def _switch_entry(self):
     surface = self.font.get_entry(int(self.builder.get_object('entry_id').get_text()))
     stack: Gtk.Stack = self.builder.get_object('entry_stack')
     if surface:
         stack.set_visible_child(self.builder.get_object('entry_viewer'))
         surface = surface.resize((surface.width*IMAGE_ZOOM, surface.height*IMAGE_ZOOM))
         self.surface = pil_to_cairo_surface(surface.convert('RGBA'))
         self.builder.get_object('draw').queue_draw()
     else:
         stack.set_visible_child(self.builder.get_object('no_entry_label'))
         self.surface = pil_to_cairo_surface(Image.new('RGBA', size=(1,1)))
예제 #4
0
 def _reinit_image(self):
     cb_store: Gtk.ListStore = self.builder.get_object('variation_store')
     cb: Gtk.ComboBoxText = self.builder.get_object('zmappat_variation')
     v: int = cb_store[cb.get_active_iter()][0]
     if self.builder.get_object('switch_minimized').get_active():
         surface = self.zmappat.to_pil_tiles_minimized(ZMappaTVariation(v))
         mask = self.zmappat.to_pil_masks_minimized(ZMappaTVariation(v))
     else:
         surface = self.zmappat.to_pil_tiles(ZMappaTVariation(v))
         mask = self.zmappat.to_pil_masks(ZMappaTVariation(v))
     surface = surface.resize((surface.width * 4, surface.height * 4))
     self.surface = pil_to_cairo_surface(surface.convert('RGBA'))
     mask = mask.resize((mask.width * 4, mask.height * 4))
     self.mask = pil_to_cairo_surface(mask.convert('RGBA'))
     self.builder.get_object('draw_tiles').queue_draw()
     self.builder.get_object('draw_masks').queue_draw()
예제 #5
0
    async def _load_object__impl(self, name, after_load_cb):
        try:
            with self._load_sprite_from_rom(f'GROUND/{name}.wan') as sprite:
                ani_group = sprite.anim_groups[0]
                frame_id = 0
                mfg_id = ani_group[frame_id].frames[0].frame_id

                sprite_img, (cx, cy) = sprite.render_frame_group(
                    sprite.frame_groups[mfg_id])
            surf = pil_to_cairo_surface(sprite_img)
            with sprite_provider_lock:
                self._loaded__objects[
                    name] = surf, cx, cy, sprite_img.width, sprite_img.height

        except BaseException as e:
            # Error :(
            logger.warning(f"Error loading an object sprite for {name}.",
                           exc_info=e)
            with sprite_provider_lock:
                self._loaded__objects[name] = self.get_error()
        with sprite_provider_lock:
            try:
                self._requests__objects.remove(name)
            except ValueError:
                pass
        after_load_cb()
예제 #6
0
 async def _load_item__impl(self, item: ItemPEntry, after_load_cb):
     try:
         assert self._dungeon_bin is not None
         with self._dungeon_bin as dungeon_bin:
             items: ImgItm = dungeon_bin.get(ITM_FILENAME)
         img = items.to_pil(item.sprite, item.palette)
         alpha = [px % 16 != 0 for px in img.getdata()]
         img = img.convert('RGBA')
         alphaimg = Image.new('1', (img.width, img.height))
         alphaimg.putdata(alpha)
         img.putalpha(alphaimg)
         surf = pil_to_cairo_surface(img)
         with sprite_provider_lock:
             self._loaded__items[item.item_id] = surf, 0, 0, 16, 16
     except BaseException as e:
         # Error :(
         logger.warning(f"Error loading an item sprite for {item}.",
                        exc_info=e)
         with sprite_provider_lock:
             self._loaded__items[item.item_id] = self.get_error()
     with sprite_provider_lock:
         try:
             self._requests__items.remove(item.item_id)
         except ValueError:
             pass
     after_load_cb()
예제 #7
0
    def on_import_icon_clicked(self, *args):
        dialog = FileChooserNative.new(
            _("Import game icon from PNG..."),
            SkyTempleMainController.window(),
            FileChooserAction.OPEN,
            None, None
        )

        add_dialog_png_filter(dialog)

        response = dialog.run()
        fn = dialog.get_filename()
        dialog.destroy()

        if response == ResponseType.ACCEPT:
            try:
                self.icon_banner.icon.from_pil(Image.open(fn))
            except Exception as err:
                display_error(
                    sys.exc_info(),
                    _('Failed importing game icon:\n') + str(err),
                    _("Could not import.")
                )
            self.icon_surface = pil_to_cairo_surface(self.icon_banner.icon.to_pil().convert('RGBA'))
            self.builder.get_object('draw_icon').queue_draw()
            # Mark as modified
            self.module.mark_as_modified()
예제 #8
0
    async def _load_monster_outline__impl(self, md_index, direction_id: int,
                                          after_load_cb):
        try:
            sprite_img, cx, cy, w, h = self._retrieve_monster_sprite(
                md_index, direction_id)

            # Convert to outline + stripes

            im_outline = sprite_img.filter(ImageFilter.FIND_EDGES)
            alpha_outline = im_outline.getchannel('A')
            im_outline = Image.new('RGBA', im_outline.size, color='white')
            im_outline.putalpha(alpha_outline)

            # /

            surf = pil_to_cairo_surface(im_outline)
            loaded = surf, cx, cy, w, h
        except BaseException:
            loaded = self.get_error()
        with sprite_provider_lock:
            self._loaded__monsters_outlines[(md_index, direction_id)] = loaded
            try:
                self._requests__monsters_outlines.remove(
                    (md_index, direction_id))
            except ValueError:
                pass
        after_load_cb()
예제 #9
0
 def _load_dtef_rendering(self):
     self.dtef = ExplorersDtef(self.dma, self.dpc, self.dpci, self.dpl, self.dpla)
     box: Gtk.Box = self.builder.get_object('dungeon_image_placeholder')
     for child in box:
         box.remove(child)
     image: Gtk.Image = Gtk.Image.new_from_surface(pil_to_cairo_surface(self.dtef.get_tiles()[0].convert('RGBA')))
     box.pack_start(image, True, True, 0)
     box.show_all()
예제 #10
0
파일: bg.py 프로젝트: tech-ticks/skytemple
 def _single_tile(self, type):
     index = self.dma.get(type, False)[0]
     chunk_dim = DPC_TILING_DIM * DPCI_TILE_DIM
     chunk_width = int(self.chunks.width / chunk_dim)
     cy = int(index / chunk_width) * chunk_dim
     cx = index % chunk_width * chunk_dim
     return pil_to_cairo_surface(
         self.chunks.crop((cx, cy, cx + chunk_dim, cy + chunk_dim)))
예제 #11
0
파일: bg.py 프로젝트: tech-ticks/skytemple
 def get_dungeon(self, rules: List[List[DmaType]]) -> cairo.Surface:
     # TODO: If rules change only update the parts that need to be updated
     if rules != self._cached_rules:
         mappings = self.dma_drawer.get_mappings_for_rules(
             rules, treat_outside_as_wall=True, variation_index=0)
         self._cached_dungeon_surface = pil_to_cairo_surface(
             self._draw_dungeon(mappings))
         self._cached_rules = rules
     return self._cached_dungeon_surface
예제 #12
0
 def _reinit_image(self):
     try:
         val = int(
             self.builder.get_object('wte_palette_variant').get_text())
     except ValueError:
         val = 0
     self.surface = pil_to_cairo_surface(
         self.wte.to_pil_canvas(val).convert('RGBA'))
     self.builder.get_object('draw').queue_draw()
예제 #13
0
    def _load_frames(self):
        with self._monster_bin as monster_bin:
            sprite = self._load_sprite_from_bin_pack(monster_bin, self.item_id)

            ani_group = sprite.get_animations_for_group(sprite.anim_groups[0])
            frame_id = 2
            for frame in ani_group[frame_id].frames:
                mfg_id = frame.frame_id
                sprite_img, (cx, cy) = sprite.render_frame_group(sprite.frame_groups[mfg_id])
                self._rendered_frame_info.append((frame.duration, (pil_to_cairo_surface(sprite_img), cx, cy, sprite_img.width, sprite_img.height)))
예제 #14
0
    def _reinit_image(self):
        cb_store: Gtk.ListStore = self.builder.get_object('cb_weather_store')
        cb: Gtk.ComboBoxText = self.builder.get_object('cb_weather')
        v : int = cb_store[cb.get_active_iter()][0]
        surface = self.colvec.to_pil(v)
        surface = surface.resize((surface.width*16, surface.height*16), resample=Image.NEAREST)
        self.colormap = pil_to_cairo_surface(surface.convert('RGBA'))

        self.surface = None
        if self.dma:
            self.dtef = ExplorersDtef(self.dma, self.dpc, self.dpci, self.dpl, self.dpla)
            surface = self.dtef.get_tiles()[0]
            
            #Apply colormap
            surface.putpalette(self.colvec.apply_colormap(v, list(surface.palette.palette)))
            self.surface = pil_to_cairo_surface(surface.convert('RGBA'))
        
        self.builder.get_object('draw_tileset').queue_draw()
        self.builder.get_object('draw_colormap').queue_draw()
예제 #15
0
 async def _load_monster__impl(self, md_index, direction_id: int,
                               after_load_cb):
     try:
         pil_img, cx, cy, w, h = self._retrieve_monster_sprite(
             md_index, direction_id)
         surf = pil_to_cairo_surface(pil_img)
         loaded = surf, cx, cy, w, h
     except BaseException:
         loaded = self.get_error()
     with sprite_provider_lock:
         self._loaded__monsters[(md_index, direction_id)] = loaded
         self._requests__monsters.remove((md_index, direction_id))
     after_load_cb()
예제 #16
0
    def _init_chunk_imgs(self):
        """(Re)-draw the chunk images"""
        self.chunks_surfaces = []

        # For each chunk...
        for chunk_idx in range(0, len(self.dpc.chunks)):
            # For each frame of palette animation... ( applicable for this chunk )
            pal_ani_frames = []
            self.chunks_surfaces.append(pal_ani_frames)

            chunk_data = self.dpc.chunks[chunk_idx]
            chunk_image = self.dpc.single_chunk_to_pil(chunk_idx, self.dpci,
                                                       self.dpl.palettes)
            has_pal_ani = any(chunk.pal_idx >= 10
                              and self.dpla.has_for_palette(chunk.pal_idx - 10)
                              for chunk in chunk_data)

            if not has_pal_ani:
                len_pal_ani = 1
            else:
                ani_pal_lengths = [
                    self.dpla.get_frame_count_for_palette(x) for x in (0, 1)
                    if self.dpla.has_for_palette(x)
                ]
                if len(ani_pal_lengths) < 2:
                    len_pal_ani = ani_pal_lengths[0]
                else:
                    len_pal_ani = lcm(*ani_pal_lengths)

            for pal_ani in range(0, len_pal_ani):
                # We don't have animated tiles, so ani_frames just has one entry.
                ani_frames = []
                pal_ani_frames.append(ani_frames)
                # Switch out the palette with that from the palette animation
                if has_pal_ani:
                    pal_for_frame = itertools.chain.from_iterable(
                        self.dpla.apply_palette_animations(
                            self.dpl.palettes, pal_ani))
                    chunk_image.putpalette(pal_for_frame)
                ani_frames.append(
                    pil_to_cairo_surface(chunk_image.convert('RGBA')))

        # TODO: No DPLA animations at different speeds supported at the moment
        ani_pal11 = 9999
        ani_pal12 = 9999
        if self.dpla.has_for_palette(0):
            ani_pal11 = self.dpla.get_duration_for_palette(0)
        if self.dpla.has_for_palette(1):
            ani_pal12 = self.dpla.get_duration_for_palette(1)

        self.pal_ani_durations = min(ani_pal11, ani_pal12)
예제 #17
0
    async def _load_actor_placeholder__impl(self, actor_id, direction_id: int,
                                            after_load_cb):
        md_index = FALLBACK_STANDIN_ENTITIY
        if actor_id in self.get_standin_entities():
            md_index = self.get_standin_entities()[actor_id]
        try:
            sprite_img, cx, cy, w, h = self._retrieve_monster_sprite(
                md_index, direction_id)

            # Convert to outline + stripes
            alpha_sprite = sprite_img.getchannel('A')

            im_outline = sprite_img.filter(ImageFilter.FIND_EDGES)
            alpha_outline = im_outline.getchannel('A')

            out_sprite = Image.new('RGBA', im_outline.size)
            for i in range(0, out_sprite.width, self._stripes.width):
                for j in range(0, out_sprite.height, self._stripes.height):
                    out_sprite.paste(self._stripes, (i, j))

            im_outline = Image.new('RGBA', im_outline.size, color='white')
            out_sprite.paste(im_outline,
                             (0, 0, im_outline.width, im_outline.height),
                             alpha_outline)

            out_sprite.putalpha(alpha_sprite)
            # Make red transparent
            data = out_sprite.getdata()
            new_data = []
            for item in data:
                if item[0] > 200 and item[1] < 200 and item[2] < 200:
                    new_data.append((255, 255, 255, 0))
                else:
                    new_data.append(item)
            out_sprite.putdata(new_data)  # type: ignore

            # /

            surf = pil_to_cairo_surface(out_sprite)
            loaded = surf, cx, cy, w, h
        except BaseException:
            loaded = self.get_error()
        with sprite_provider_lock:
            self._loaded__actor_placeholders[(actor_id, direction_id)] = loaded
            try:
                self._requests__actor_placeholders.remove(
                    (actor_id, direction_id))
            except ValueError:
                pass
        after_load_cb()
예제 #18
0
 def on_tool_choose_map_bg_cb_changed(self, w: Gtk.ComboBox):
     model, cbiter = w.get_model(), w.get_active_iter()
     if model is not None and cbiter is not None and cbiter != []:
         item_id = model[cbiter][0]
         self.mapbg_id = item_id
         bma = self.map_bg_module.get_bma(item_id)
         bpl = self.map_bg_module.get_bpl(item_id)
         bpc = self.map_bg_module.get_bpc(item_id)
         bpas = self.map_bg_module.get_bpas(item_id)
         self._map_bg_surface = pil_to_cairo_surface(
             bma.to_pil(bpc, bpl, bpas, False, False, single_frame=True)[0].convert('RGBA')
         )
         bma_width = bma.map_width_camera * BPC_TILE_DIM
         bma_height = bma.map_height_camera * BPC_TILE_DIM
         if self.drawer:
             self._set_drawer_bg(self._map_bg_surface, bma_width, bma_height)
예제 #19
0
파일: font.py 프로젝트: retke/skytemple
 def _switch_table(self):
     cb_store: Gtk.ListStore = self.builder.get_object('table_store')
     cb: Gtk.ComboBoxText = self.builder.get_object('cb_table_select')
     if cb.get_active_iter()!=None:
         v : int = cb_store[cb.get_active_iter()][0]
         self.entries = self.font.get_entries_from_table(v)
         
         entry_tree: Gtk.TreeView = self.builder.get_object('entry_tree')
         store: Gtk.ListStore = entry_tree.get_model()
         store.clear()
         
         for e in self.entries:
             self._add_property_row(store, e)
         surface = self.tables[v].resize((self.tables[v].width*IMAGE_ZOOM, self.tables[v].height*IMAGE_ZOOM))
         self.surface = pil_to_cairo_surface(surface.convert('RGBA'))
         self.builder.get_object('draw').queue_draw()
예제 #20
0
    def get_view(self) -> Widget:
        self.builder = self._get_builder(__file__, 'rom.glade')

        file_name = os.path.basename(self.module.project.filename)
        self.builder.get_object('file_name').set_text(file_name)

        self.builder.get_object('name').set_text(self.project.get_rom_name())
        self.builder.get_object('id_code').set_text(self.project.get_id_code())
        self.icon_surface = pil_to_cairo_surface(
            self.icon_banner.icon.to_pil().convert('RGBA'))

        title_japanese_buffer = self.builder.get_object(
            'title_japanese').get_buffer()
        title_japanese_buffer.set_text(self.icon_banner.title_japanese)
        title_japanese_buffer.connect('changed',
                                      self.on_title_japanese_changed)

        title_english_buffer = self.builder.get_object(
            'title_english').get_buffer()
        title_english_buffer.set_text(self.icon_banner.title_english)
        title_english_buffer.connect('changed', self.on_title_english_changed)

        title_french_buffer = self.builder.get_object(
            'title_french').get_buffer()
        title_french_buffer.set_text(self.icon_banner.title_french)
        title_french_buffer.connect('changed', self.on_title_french_changed)

        title_german_buffer = self.builder.get_object(
            'title_german').get_buffer()
        title_german_buffer.set_text(self.icon_banner.title_german)
        title_german_buffer.connect('changed', self.on_title_german_changed)

        title_italian_buffer = self.builder.get_object(
            'title_italian').get_buffer()
        title_italian_buffer.set_text(self.icon_banner.title_italian)
        title_italian_buffer.connect('changed', self.on_title_italian_changed)

        title_spanish_buffer = self.builder.get_object(
            'title_spanish').get_buffer()
        title_spanish_buffer.set_text(self.icon_banner.title_spanish)
        title_spanish_buffer.connect('changed', self.on_title_spanish_changed)

        self.builder.connect_signals(self)

        return self.builder.get_object('box_list')
예제 #21
0
    async def _load_trap__impl(self, trp: int, after_load_cb):
        try:
            with self._dungeon_bin as dungeon_bin:
                traps: ImgTrp = dungeon_bin.get(TRP_FILENAME)
            surf = pil_to_cairo_surface(
                traps.to_pil(trp, TRAP_PALETTE_MAP[trp]).convert('RGBA'))
            with sprite_provider_lock:
                self._loaded__traps[trp] = surf, 0, 0, 24, 24

        except BaseException as e:
            # Error :(
            logger.warning(f"Error loading an trap sprite for {trp}.",
                           exc_info=e)
            with sprite_provider_lock:
                self._loaded__traps[trp] = self.get_error()
        with sprite_provider_lock:
            self._requests__traps.remove(trp)
        after_load_cb()
예제 #22
0
 def draw_full(self, ctx: cairo.Context, bma_chunks: List[int],
               bma_chunk_width: int, bma_chunk_height: int):
     if bma_chunk_width != self._cached__bma_chunk_width or self._cached__bma_chunks != bma_chunks:
         self._cached__bma_chunk_width = bma_chunk_width
         self._cached__bma_chunks = list(bma_chunks)
         self._cached = None
     if self._cached is None:
         drawer = DmaDrawer(self.dma)
         if self.fixed_room:
             rules = drawer.rules_from_fixed_room(self.fixed_room)
         else:
             rules = drawer.rules_from_bma(bma_chunks, bma_chunk_width)
         mappings = drawer.get_mappings_for_rules(
             rules, treat_outside_as_wall=True, variation_index=0)
         frame = pil_to_cairo_surface(
             drawer.draw(mappings, self.dpci, self.dpc, self.dpl,
                         None)[0].convert('RGBA'))
         self._cached = frame
     ctx.set_source_surface(self._cached)
     ctx.get_source().set_filter(cairo.Filter.NEAREST)
     ctx.paint()
예제 #23
0
 async def _load__impl(self, entry_id, sub_id, after_load_cb, allow_fallback):
     is_fallback = False
     try:
         kao = self._kao.get(entry_id, sub_id)
         if kao is None or kao.empty is True:
             if allow_fallback:
                 is_fallback = True
                 kao = self._kao.get(entry_id % NUM_ENTITIES, sub_id)
                 if kao is None:
                     raise RuntimeError()
             else:
                 raise RuntimeError()
         portrait_pil = kao.get()
         surf = pil_to_cairo_surface(portrait_pil.convert('RGBA'))
         loaded = surf
     except (RuntimeError, ValueError):
         loaded = self.get_error()
     with portrait_provider_lock:
         self._loaded[(entry_id, sub_id)] = loaded
         self._loaded__is_fallback[(entry_id, sub_id)] = is_fallback
         self._requests.remove((entry_id, sub_id))
     after_load_cb()
예제 #24
0
    def get_dungeon(self, rules: List[List[DmaType]]) -> cairo.Surface:
        if rules != self._cached_rules:
            surf = pil_to_cairo_surface(Image.new(
                'RGBA', size=(len(rules[0] * ZMAPPAT_DIM), len(rules * ZMAPPAT_DIM)), color=(0, 0, 231, 255)
            ))
            ctx = cairo.Context(surf)
            for y, row in enumerate(rules):
                for x, cell in enumerate(row):
                    if cell == DmaType.WALL:
                        continue
                    self.paint(ctx, self.get_single_tile(cell), x * ZMAPPAT_DIM, y * ZMAPPAT_DIM)
                    if cell == DmaType.WATER:
                        self.paint(ctx, self.minimap_provider.get_secondary_tile(), x * ZMAPPAT_DIM, y * ZMAPPAT_DIM)
                    else:
                        w_below = self.w_below(rules, x, y)  # 0001
                        w_right = self.w_right(rules, x, y)  # 0010
                        w_above = self.w_above(rules, x, y)  # 0100
                        w_left = self.w_left(rules, x, y)    # 1000
                        idx = 16 + w_below + 2 * w_right + 4 * w_above + 8 * w_left
                        self.paint(ctx, self.minimap_provider.get_minimap_tile(idx), x * ZMAPPAT_DIM, y * ZMAPPAT_DIM)

            self._cached_dungeon_surface = surf
            self._cached_rules = rules
        return self._cached_dungeon_surface  # type: ignore
예제 #25
0
 def _reinit_image(self):
     surface = self.module.get_cart_removed_data()
     self.surface = pil_to_cairo_surface(surface.convert('RGBA'))
     self.builder.get_object('draw').queue_draw()
예제 #26
0
 def _single_tile(self, chunks, type):
     index = self.dma.get(type, False)[0]
     chunk_dim = DPC_TILING_DIM * DPCI_TILE_DIM
     return pil_to_cairo_surface(
         chunks.crop((0, index * chunk_dim, chunk_dim, index * chunk_dim + chunk_dim)).convert('RGBA')
     )
예제 #27
0
 def _reinit_image(self):
     variant = int(self.builder.get_object('chr_palette_variant').get_text())
     surface = self.chr.to_pil(variant)
     self.surface = pil_to_cairo_surface(surface.convert('RGBA'))
     self.builder.get_object('draw').queue_draw()
예제 #28
0
    def __init__(self,
                 parent_window,
                 incoming_mappings: List[TilemapEntry],
                 tile_graphics: AbstractTileGraphicsProvider,
                 palettes: AbstractTilePalettesProvider,
                 pal_ani_durations: int,
                 animated_tile_graphics: List[
                     Optional[AbstractTileGraphicsProvider]] = None,
                 animated_tile_durations=0):
        path = os.path.abspath(os.path.dirname(__file__))

        self.builder = make_builder(os.path.join(path, 'chunk_editor.glade'))

        self.dialog: Gtk.Dialog = self.builder.get_object(
            'map_bg_chunk_editor')
        self.dialog.set_attached_to(parent_window)
        self.dialog.set_transient_for(parent_window)

        self.tile_graphics = tile_graphics
        self.animated_tile_graphics = animated_tile_graphics
        self.palettes = palettes
        self.animated_tile_durations = animated_tile_durations
        self.pal_ani_durations = pal_ani_durations

        self.current_tile_id = 0
        self.current_tile_drawer: DrawerTiled = None

        self.switching_tile = False

        self.edited_mappings = []
        for mapping in incoming_mappings:
            self.edited_mappings.append(TilemapEntry.from_int(
                mapping.to_int()))

        self.tile_surfaces = []
        # For each palette
        for pal in range(0, len(self.palettes.get())):
            all_bpc_tiles_for_current_pal = self.tile_graphics.get_pil(
                self.palettes.get(), pal)
            tiles_current_pal = []
            self.tile_surfaces.append(tiles_current_pal)

            has_pal_ani = self.palettes.is_palette_affected_by_animation(pal)
            len_pal_ani = self.palettes.animation_length(
            ) if has_pal_ani else 1

            # BPC tiles
            # For each tile...
            for tile_idx in range(0, self.tile_graphics.count()):
                # For each frame of palette animation...
                pal_ani_tile = []
                tiles_current_pal.append(pal_ani_tile)
                for pal_ani in range(0, len_pal_ani):
                    # Switch out the palette with that from the palette animation
                    if has_pal_ani:
                        pal_for_frame = itertools.chain.from_iterable(
                            self.palettes.apply_palette_animations(pal_ani))
                        all_bpc_tiles_for_current_pal.putpalette(pal_for_frame)
                    pal_ani_tile.append([
                        pil_to_cairo_surface(
                            all_bpc_tiles_for_current_pal.crop(
                                (0, tile_idx * TILE_DIM, TILE_DIM,
                                 tile_idx * TILE_DIM +
                                 TILE_DIM)).convert('RGBA'))
                    ])
            # BPA tiles
            # For each BPA...
            if self.animated_tile_graphics is not None:
                for ani_tile_g in self.animated_tile_graphics:
                    if ani_tile_g is not None:
                        all_bpa_tiles_for_current_pal = ani_tile_g.get_pil(
                            self.palettes.get(), pal)
                        # For each tile...
                        for tile_idx in range(0, ani_tile_g.count()):
                            pal_ani_tile = []
                            tiles_current_pal.append(pal_ani_tile)
                            # For each frame of palette animation...
                            for pal_ani in range(0, len_pal_ani):
                                bpa_ani_tile = []
                                pal_ani_tile.append(bpa_ani_tile)
                                # For each frame of BPA animation...
                                for frame in all_bpa_tiles_for_current_pal:
                                    # Switch out the palette with that from the palette animation
                                    if has_pal_ani:
                                        pal_for_frame = itertools.chain.from_iterable(
                                            self.palettes.
                                            apply_palette_animations(pal_ani))
                                        all_bpc_tiles_for_current_pal.putpalette(
                                            pal_for_frame)
                                    bpa_ani_tile.append(
                                        pil_to_cairo_surface(
                                            frame.crop(
                                                (0, tile_idx * TILE_DIM,
                                                 TILE_DIM,
                                                 tile_idx * TILE_DIM +
                                                 TILE_DIM)).convert('RGBA')))

            self.builder.connect_signals(self)

            self.dummy_tile_map = []
            self.current_tile_picker_palette = 0
            for i in range(0, self.tile_graphics.count()):
                self.dummy_tile_map.append(
                    TilemapEntry(idx=i,
                                 pal_idx=self.current_tile_picker_palette,
                                 flip_x=False,
                                 flip_y=False))

            if self.animated_tile_graphics:
                self.bpa_starts_cursor = len(self.dummy_tile_map)
                self.bpa_starts = [None, None, None, None]
                for i, ani_tile_g in enumerate(self.animated_tile_graphics):
                    if ani_tile_g is not None:
                        self.bpa_starts[i] = self.bpa_starts_cursor
                        self.current_tile_picker_palette = 0
                        for j in range(0, ani_tile_g.count()):
                            self.dummy_tile_map.append(
                                TilemapEntry(
                                    idx=self.bpa_starts_cursor + j,
                                    pal_idx=self.current_tile_picker_palette,
                                    flip_x=False,
                                    flip_y=False))
                        self.bpa_starts_cursor += ani_tile_g.count()
예제 #29
0
파일: bg.py 프로젝트: tech-ticks/skytemple
    def _init_chunk_imgs(self):
        """(Re)-draw the chunk images"""

        # Set the weird palette warning to false
        self.weird_palette = False

        if self.bpc.number_of_layers > 1:
            layer_idxs_bpc = [1, 0]
        else:
            layer_idxs_bpc = [0]

        self.chunks_surfaces = []

        # For each layer...
        for layer_idx, layer_idx_bpc in enumerate(layer_idxs_bpc):
            chunks_current_layer = []
            self.chunks_surfaces.append(chunks_current_layer)
            # For each chunk...
            for chunk_idx in range(
                    0, self.bpc.layers[layer_idx_bpc].chunk_tilemap_len):
                # For each frame of palette animation... ( applicable for this chunk )
                pal_ani_frames = []
                chunks_current_layer.append(pal_ani_frames)

                chunk_data = self.bpc.get_chunk(layer_idx_bpc, chunk_idx)
                chunk_images = self.bpc.single_chunk_animated_to_pil(
                    layer_idx_bpc, chunk_idx, self.bpl.palettes, self.bpas)
                if not self.weird_palette:
                    for x in chunk_images:
                        for n in x.tobytes("raw", "P"):
                            n //= 16
                            if n >= self.bpl.number_palettes or n >= BPL_NORMAL_MAX_PAL:
                                # If one chunk uses weird palette values, display the warning
                                self.weird_palette = True
                                break
                        if self.weird_palette: break
                has_pal_ani = any(
                    self.bpl.is_palette_affected_by_animation(chunk.pal_idx)
                    for chunk in chunk_data)
                len_pal_ani = len(
                    self.bpl.animation_palette) if has_pal_ani else 1

                for pal_ani in range(0, len_pal_ani):
                    # For each frame of tile animation...
                    bpa_ani_frames = []
                    pal_ani_frames.append(bpa_ani_frames)
                    for img in chunk_images:
                        # Switch out the palette with that from the palette animation
                        if has_pal_ani:
                            pal_for_frame = itertools.chain.from_iterable(
                                self.bpl.apply_palette_animations(pal_ani))
                            img.putpalette(pal_for_frame)
                        # Remove alpha first
                        img_mask = img.copy()
                        img_mask.putpalette(MASK_PAL)
                        img_mask = img_mask.convert('1')
                        img = img.convert('RGBA')
                        img.putalpha(img_mask)
                        bpa_ani_frames.append(pil_to_cairo_surface(img))

            # TODO: No BPAs at different speeds supported at the moment
            self.bpa_durations = 0
            for bpa in self.bpas:
                if bpa is not None:
                    single_bpa_duration = max(
                        info.duration_per_frame
                        for info in bpa.frame_info) if len(
                            bpa.frame_info) > 0 else 9999
                    if single_bpa_duration > self.bpa_durations:
                        self.bpa_durations = single_bpa_duration

            # TODO: No BPL animations at different speeds supported at the moment
            self.pal_ani_durations = 0
            if self.bpl.has_palette_animation:
                self.pal_ani_durations = max(
                    spec.duration_per_frame
                    for spec in self.bpl.animation_specs)
        self.set_warning_palette()
예제 #30
0
파일: bg.py 프로젝트: tech-ticks/skytemple
 def get_background(self) -> Optional[cairo.Surface]:
     if not self._cached_bg:
         self._cached_bg = pil_to_cairo_surface(
             self.dbg.to_pil(self.dbg_dpc, self.dbg_dpci,
                             self.dbg_dpl.palettes).convert('RGBA'))
     return self._cached_bg