Exemple #1
0
    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()
Exemple #2
0
    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)
Exemple #3
0
    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.")
Exemple #4
0
    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()
Exemple #5
0
    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)
Exemple #6
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()
Exemple #7
0
    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)
Exemple #8
0
    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)
Exemple #9
0
    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))
Exemple #10
0
    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)
Exemple #11
0
    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)
Exemple #12
0
    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()
Exemple #13
0
    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)
Exemple #14
0
    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)
Exemple #15
0
    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)
Exemple #16
0
    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()
Exemple #17
0
    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)
Exemple #18
0
    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()
Exemple #19
0
    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()