def on_spritebot_import_activate(self, *args): dialog = Gtk.FileChooserNative.new( _("Import portraits from PNG sheet..."), MainController.window(), Gtk.FileChooserAction.OPEN, None, None) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: try: for subindex, image in SpriteBotSheet.load( fn, self._get_portrait_name): try: self.kao.set_from_img(self.item_id, subindex, image) except Exception as err: name = self._get_portrait_name(subindex) logger.error(f"Failed importing image '{name}'.", exc_info=err) display_error( sys.exc_info(), f(_('Failed importing image "{name}":\n{err}')), f(_("Error for '{name}'."))) except Exception as err: logger.error(f"Failed importing portraits sheet: {err}", exc_info=err) display_error(sys.exc_info(), f(_('Failed importing portraits sheet:\n{err}')), _("Could not import.")) self.re_render() # Mark as modified self.module.mark_as_modified() self._mark_as_modified_cb()
def on_men_bg_export_activate(self, *args): dialog: Gtk.Dialog = self.builder.get_object('dialog_bg_export') dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) resp = dialog.run() dialog.hide() if resp == ResponseType.OK: dialog = Gtk.FileChooserNative.new( "Export as PNG...", MainController.window(), Gtk.FileChooserAction.SAVE, None, None ) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() if '.' not in fn: fn += '.png' dialog.destroy() if response == Gtk.ResponseType.ACCEPT: self.bgp.to_pil().save(fn)
def on_men_tiles_layer1_export_activate(self): dialog: Gtk.Dialog = self.parent.builder.get_object( 'dialog_tiles_export') dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) resp = dialog.run() dialog.hide() if resp == Gtk.ResponseType.OK: dialog = Gtk.FileChooserNative.new("Export PNG of tiles...", MainController.window(), Gtk.FileChooserAction.SAVE, None, None) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() if '.' not in fn: fn += '.png' dialog.destroy() if response == Gtk.ResponseType.ACCEPT: try: self.parent.dpci.tiles_to_pil(self.parent.dpl.palettes, 16).save(fn) except BaseException as err: display_error(sys.exc_info(), str(err), "Error exporting the tileset.")
def on_import_clicked(self, w: Gtk.MenuToolButton): dialog = Gtk.FileChooserNative.new( _("Import image as indexed PNG..."), MainController.window(), Gtk.FileChooserAction.OPEN, _("_Open"), None ) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: try: img = Image.open(fn, 'r') self.chr.from_pil(img) except Exception as err: display_error( sys.exc_info(), str(err), _("Error importing chr image.") ) self.module.mark_chr_as_modified(self.filename) self._reinit_image()
def _export_tiles(self, layer): dialog: Gtk.Dialog = self.parent.builder.get_object( 'dialog_tiles_export') dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) resp = dialog.run() dialog.hide() if resp == ResponseType.OK: dialog = Gtk.FileChooserNative.new(_("Export PNG of tiles..."), MainController.window(), Gtk.FileChooserAction.SAVE, None, None) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() if '.' not in fn: fn += '.png' dialog.destroy() if response == Gtk.ResponseType.ACCEPT: self.parent.bpc.tiles_to_pil(layer, self.parent.bpl.palettes, 20).save(fn)
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()
def on_export_icon_clicked(self, *args): dialog = FileChooserNative.new(_("Export game icon as PNG..."), SkyTempleMainController.window(), FileChooserAction.SAVE, None, None) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == ResponseType.ACCEPT: fn = add_extension_if_missing(fn, 'png') self.icon_banner.icon.to_pil().save(fn)
def on_spritebot_export_activate(self, *args): dialog = Gtk.FileChooserNative.new( _("Export portrait as PNG sheet..."), MainController.window(), Gtk.FileChooserAction.SAVE, None, None) add_dialog_png_filter(dialog) response = dialog.run() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: fn = dialog.get_filename() fn = add_extension_if_missing(fn, 'png') SpriteBotSheet.create(self.kao, self.item_id).save(fn)
def on_dialog_tiles_animated_export_export_btn_clicked(self): bpa_select = self.parent.builder.get_object( 'dialog_tiles_animated_export_select_bpa') active_bpa_index = bpa_select.get_model()[ bpa_select.get_active_iter()][1] active_bpa = self.parent.bpas[active_bpa_index] is_single_mode = self.parent.builder.get_object( 'dialog_tiles_animated_export_radio_single').get_active() file_chooser_mode = Gtk.FileChooserAction.SAVE if is_single_mode else Gtk.FileChooserAction.SELECT_FOLDER dialog = Gtk.FileChooserNative.new(_("Export animated tiles (BPA)"), MainController.window(), file_chooser_mode, None, None) if is_single_mode: add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: # TODO: Support specifying palette pal = self.parent.bpl.palettes[0] try: if is_single_mode: if not fn.endswith('.png'): fn += '.png' active_bpa.tiles_to_pil(pal).save(fn) else: for i, img in enumerate( active_bpa.tiles_to_pil_separate(pal, 20)): img.save( os.path.join( fn, self._get_bpa_export_name_pattern( active_bpa_index + 1, i))) md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("The animated tiles were successfully exported."), title=_("SkyTemple - Success!"), is_success=True) md.run() md.destroy() except Exception as err: logger.error(_("Error during BPA export"), exc_info=err) display_error(sys.exc_info(), str(err))
def on_export_clicked(self, w: Gtk.MenuToolButton): dialog = Gtk.FileChooserNative.new(_("Export image as PNG..."), MainController.window(), Gtk.FileChooserAction.SAVE, _("_Save"), None) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: fn = add_extension_if_missing(fn, 'png') self.module.get_cart_removed_data().save(fn)
def on_export_clicked(self, w: Gtk.MenuToolButton): dialog = Gtk.FileChooserNative.new(_("Export image as PNG..."), MainController.window(), Gtk.FileChooserAction.SAVE, _("_Save"), None) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: if '.' not in fn: fn += '.png' self.chr.to_pil().save(fn)
def on_spritebot_import_activate(self, *args): dialog = Gtk.FileChooserNative.new( "Import portraits from PNG sheet...", MainController.window(), Gtk.FileChooserAction.OPEN, None, None) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: try: for subindex, image in SpriteBotSheet.load( fn, self._get_portrait_name): try: kao = self.kao.get(self.item_id, subindex) if kao: # Replace kao.set(image) else: # New self.kao.set(self.item_id, subindex, KaoImage.new(image)) except Exception as err: name = self._get_portrait_name(subindex) logger.error(f"Failed importing image '{name}'.", exc_info=err) display_error( sys.exc_info(), f'Failed importing image "{name}":\n{err}', f"Error for '{name}'.") except Exception as err: logger.error(f"Failed importing portraits sheet: {err}", exc_info=err) display_error(sys.exc_info(), f'Failed importing portraits sheet:\n{err}', f"Could not import.") # Re-render self._portrait_provider.reset() for draw in self._draws: draw.queue_draw() # Mark as modified self.module.mark_as_modified() self._mark_as_modified_cb()
def on_export_clicked(self, *args): 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] dialog = Gtk.FileChooserNative.new( _("Export current colormap as PNG..."), MainController.window(), Gtk.FileChooserAction.SAVE, "_Save", None) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: fn = add_extension_if_missing(fn, 'png') self.colvec.to_pil(v).save(fn)
def on_export_clicked(self, w: Gtk.MenuToolButton): dialog = Gtk.FileChooserNative.new("Export image as PNG...", MainController.window(), Gtk.FileChooserAction.SAVE, "_Save", None) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: if '.' not in fn: fn += '.png' if self.wte.has_image(): self.wte.to_pil_canvas().save(fn) else: self.wte.to_pil_palette().save(fn)
def on_import_clicked(self, w: Gtk.MenuToolButton): dialog = Gtk.FileChooserNative.new( _("Import image..."), MainController.window(), Gtk.FileChooserAction.OPEN, None, None ) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: assert self.builder dialog = self.builder.get_object('dialog_import') dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) resp = dialog.run() dialog.hide() if resp == Gtk.ResponseType.OK: import_palette = self.builder.get_object('switch_import_palette').get_active() import_new = self.builder.get_object('switch_import_new').get_active() img = Image.open(fn) if import_new: idx = len(self.img.sprites) self.img.sprites.append(None) # type: ignore else: idx = self.image_idx try: self.img.from_pil(idx, img, import_palette) self.module.mark_icons_as_modified(self.img_type, self.img) self.module.project.get_sprite_provider().reset() except Exception as err: display_error( sys.exc_info(), str(err), "Error importing sprite." ) self._init_sprites(idx, self.palette_idx)
def on_import_clicked(self, w: Gtk.MenuToolButton): dialog = Gtk.FileChooserNative.new("Import image as PNG...", MainController.window(), Gtk.FileChooserAction.OPEN, "_Open", None) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: try: img = Image.open(fn, 'r') self.module.set_cart_removed_data(img) except Exception as err: display_error(sys.exc_info(), str(err), "Error importing cart removed image.") self._reinit_image()
def on_export_clicked(self, w: Gtk.MenuToolButton): dialog = Gtk.FileChooserNative.new(_("Export image as PNG..."), MainController.window(), Gtk.FileChooserAction.SAVE, _("_Save"), None) add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: fn = add_extension_if_missing(fn, 'png') if self.wte.has_image(): self.wte.to_pil_canvas( int( self.builder.get_object( 'wte_palette_variant').get_text())).save( fn) # type: ignore else: self.wte.to_pil_palette().save(fn)
def on_dialog_tiles_animated_export_import_btn_clicked(self): bpa_select = self.parent.builder.get_object( 'dialog_tiles_animated_export_select_bpa') active_bpa_index = bpa_select.get_model()[ bpa_select.get_active_iter()][1] active_bpa = self.parent.bpas[active_bpa_index] is_single_mode = self.parent.builder.get_object( 'dialog_tiles_animated_export_radio_single').get_active() file_chooser_mode = Gtk.FileChooserAction.OPEN if is_single_mode else Gtk.FileChooserAction.SELECT_FOLDER dialog = Gtk.FileChooserNative.new(_("Import animated tiles (BPA)"), MainController.window(), file_chooser_mode, None, None) if is_single_mode: add_dialog_png_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: try: if is_single_mode: filenames_base = [os.path.basename(fn)] with open(fn, 'rb') as f: active_bpa.pil_to_tiles(Image.open(f)) self.parent.bpc.process_bpa_change( active_bpa_index, active_bpa.number_of_tiles) else: r = re.compile( f"{self.parent.module.bgs.level[self.parent.item_id].bma_name}_bpa{active_bpa_index+1}_\d+\.png", re.IGNORECASE) filenames_base = natsorted(filter(r.match, os.listdir(fn)), alg=ns.IGNORECASE) img_handles = [ open(os.path.join(fn, base_name), 'rb') for base_name in filenames_base ] try: images = [Image.open(h) for h in img_handles] active_bpa.pil_to_tiles_separate(images) self.parent.bpc.process_bpa_change( active_bpa_index, active_bpa.number_of_tiles) finally: for handle in img_handles: handle.close() # Don't forget to update the BPC! bpa_relative_idx = active_bpa_index % 4 bpc_layer_for_bpa = 0 if active_bpa_index < 4 else 1 self.parent.bpc.layers[bpc_layer_for_bpa].bpas[ bpa_relative_idx] = active_bpa.number_of_tiles md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("The animated tiles were successfully imported, using the files: " ) + ', '.join(filenames_base) + ".", title=_("SkyTemple - Success!"), is_success=True) md.run() md.destroy() except Exception as err: logger.error(_("Error during BPA import"), exc_info=err) display_error(sys.exc_info(), str(err)) self.parent.reload_all() self.parent.mark_as_modified()
def convert(self, *args): mode_cb: Gtk.ComboBox = self.builder.get_object('tq_mode') mode = ImageConversionMode( mode_cb.get_model()[mode_cb.get_active_iter()][0]) dither_level = self.builder.get_object('tq_dither_level').get_value() has_first_image = self.builder.get_object( 'tq_input_file').get_filename() is not None has_second_image = self.builder.get_object( 'tq_second_file').get_filename() is not None if not has_first_image: self.error(_("Please select an input image."), should_report=False) return if has_second_image: md = SkyTempleMessageDialog( self.window, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("Since you selected two images to convert, you will be " "asked for both images where to save them to.")) md.run() md.destroy() dialog = Gtk.FileChooserNative.new(_("Save first image as (PNG)..."), self.window, Gtk.FileChooserAction.SAVE, None, None) if self._previous_output_image is not None: dialog.set_filename(self._previous_output_image) add_dialog_png_filter(dialog) response = dialog.run() output_image = dialog.get_filename() if output_image and '.' not in output_image: output_image += '.png' self._previous_output_image = output_image dialog.destroy() if response != Gtk.ResponseType.ACCEPT: return if has_second_image: dialog = Gtk.FileChooserNative.new( _("Save second image as (PNG)..."), self.window, Gtk.FileChooserAction.SAVE, None, None) if self._previous_second_output_image is not None: dialog.set_filename(self._previous_second_output_image) else: dialog.set_filename(output_image) add_dialog_png_filter(dialog) response = dialog.run() second_output_image = dialog.get_filename() if '.' not in second_output_image: second_output_image += '.png' self._previous_second_output_image = second_output_image dialog.destroy() if response != Gtk.ResponseType.ACCEPT: return try: num_pals = int( self.builder.get_object('tq_number_palettes').get_text()) input_image = self.builder.get_object( 'tq_input_file').get_filename() second_input_file = self.builder.get_object( 'tq_second_file').get_filename() transparent_color = self.builder.get_object( 'tq_transparent_color').get_color() transparent_color = (int(transparent_color.red_float * 255), int(transparent_color.green_float * 255), int(transparent_color.blue_float * 255)) except ValueError: self.error(_("You entered invalid numbers."), should_report=False) else: if not os.path.exists(input_image): self.error(_("The input image does not exist."), should_report=False) return if has_second_image and not os.path.exists(second_input_file): self.error(_("The second input image does not exist."), should_report=False) return with open(input_image, 'rb') as input_file: try: if not has_second_image: # Only one image image = Image.open(input_file) else: # Two images: Merge them. image1 = Image.open(input_file) image2 = Image.open(second_input_file) image = Image.new('RGBA', (max(image1.width, image2.width), image1.height + image2.height), transparent_color) image.paste(image1, (0, 0)) image.paste(image2, (0, image1.height)) except OSError: self.error(_("The input image is not a supported format."), should_report=False) return try: img = self._convert(image, transparent_color, mode, num_pals, dither_level) if not has_second_image: # Only one image img.save(output_image) else: # Two images: Un-merge them. img.crop((0, 0, image1.width, image1.height)).save(output_image) img.crop( (0, image1.height, image2.width, image1.height + image2.height)).save(second_output_image) except BaseException as err: logger.error("Tilequant error.", exc_info=err) self.error(str(err)) else: md = SkyTempleMessageDialog( self.window, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("Image was converted."), is_success=True) md.run() md.destroy()