def on_btn_add_clicked(self, *args): response, new_name = self._show_generic_input( _('Level Name'), _('Create Level'), (_('If you also need a new background for this level, you can ' 'create one under "Map Backrgounds" and assign it to this ' 'level afterwards.'))) if response != Gtk.ResponseType.OK: return new_name = new_name.upper() if len(new_name) < 1 or len(new_name) > 8: md = SkyTempleMessageDialog( SkyTempleMainController.window(), Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, _("The length of the level name must be between 1-8 characters." )) md.run() md.destroy() return new_id = max(l.id for l in self._list.list) + 1 store: Gtk.ListStore = self.builder.get_object('level_list_tree_store') store.append([ str(new_id), new_name, 0, 0, 0, str(-1), self._labels_overworld_strings[0], self._labels_maptype[0], self._labels_mapid[0] ]) self.module.create_new_level(new_name) self._save() md = SkyTempleMessageDialog(SkyTempleMainController.window(), Gtk.DialogFlags.MODAL, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("New level created."), is_success=True) md.run() md.destroy()
def on_btn_add_acting_clicked(self, *args): response, name = self._show_generic_input( _('Scene Name (without file extension)'), _('Create Scene')) if response != Gtk.ResponseType.OK: return name_file = name.lower() if len(name) < 1 or len(name) > 8: md = SkyTempleMessageDialog( SkyTempleMainController.window(), Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, _("The length of the scene name must be between 1-8 characters." )) md.run() md.destroy() return try: self.module.add_scene_acting(self.name, name_file) except ValueError as err: md = SkyTempleMessageDialog( SkyTempleMainController.window(), Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, _("Could not add the scene: ") + str(err)) md.run() md.destroy() return md = SkyTempleMessageDialog(SkyTempleMainController.window(), Gtk.DialogFlags.MODAL, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("Scene added successfully"), is_success=True) md.run() md.destroy()
def on_btn_apply_size_clicked(self, *args): try: width = int(self.builder.get_object('settings_width').get_text()) height = int(self.builder.get_object('settings_height').get_text()) if width == 0 or height == 0: # 0x0 rooms are allowed to be consistent with the fact that they exist width = height = 0 assert width >= 0 and height >= 0 except (ValueError, AssertionError): display_error(sys.exc_info(), _("Width and height must be numbers >= 0."), _("Invalid values.")) return confirm = True if width < self.floor.width or height < self.floor.height: md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.MODAL, Gtk.MessageType.WARNING, Gtk.ButtonsType.YES_NO, _("You are about to reduce the size of the room. This will delete tiles. Do you want to continue?" ), title=_("Warning!")) response = md.run() md.destroy() confirm = response == Gtk.ResponseType.YES if confirm: self.floor.resize(width, height) self.module.mark_fixed_floor_as_modified(self.floor_id) MainController.reload_view()
def _create_scene_file(self, level_name, scene_name, ext, matching_ssb=None): dir_name = f"{SCRIPT_DIR}/{level_name}" if '.' in scene_name: raise ValueError( _("The file name provided must not have a file extension.")) if len(scene_name) > 8: raise ValueError( _("The file name provided is too long (max 8 characters).")) ssx_name = f"{dir_name}/{scene_name}.{ext}" self.project.ensure_dir(dir_name) self.project.create_new_file(ssx_name, self._get_empty_scene(), FileType.SSA) if matching_ssb is not None: ssb_name = f"{dir_name}/{scene_name}{matching_ssb}.ssb" save_kwargs = { 'filename': ssb_name, 'static_data': self.project.get_rom_module().get_static_data(), 'project_fm': self.project.get_project_file_manager() } self.project.create_new_file( ssb_name, SsbLoadedFileHandler.create(**save_kwargs), SsbLoadedFileHandler, **save_kwargs) # Update debugger SkyTempleMainController.debugger_manager().on_script_added( ssb_name, level_name, ext, f'{scene_name}.{ext}') return ssx_name, ssb_name else: return ssx_name, None
def import_a_sprite__gfxcrunch(self) -> Optional[bytes]: md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, "To import select the directory of the sprite export. If it " "is still zipped, unzip it first.", title="SkyTemple") md.run() md.destroy() dialog = Gtk.FileChooserNative.new("Import gfxcrunch sprite...", MainController.window(), Gtk.FileChooserAction.SELECT_FOLDER, None, None) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: try: return self.get_gfxcrunch().import_sprite(fn) except BaseException as e: display_error(sys.exc_info(), str(e), "Error importing the sprite.") return None
def on_men_palettes_ani_settings_activate(self): dialog: Gtk.Dialog = self.parent.builder.get_object( 'dialog_palettes_animated_settings') dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) self.parent.builder.get_object( 'palette_animation11_enabled').set_active( self.parent.dpla.has_for_palette(0)) self.parent.builder.get_object( 'palette_animation12_enabled').set_active( self.parent.dpla.has_for_palette(1)) for aidx, offset in (11, 0), (12, 16): for cidx in range(0, 16): self.parent.builder.get_object( f'palette_animation{aidx}_frame_time{cidx}').set_text( str(self.parent.dpla.durations_per_frame_for_colors[ offset + cidx])) response = dialog.run() dialog.hide() if response == Gtk.ResponseType.OK: had_errors = False for palid, aidx, offset in ((0, 11, 0), (1, 12, 16)): if self.parent.builder.get_object( f'palette_animation{aidx}_enabled').get_active(): # Has palette animations! self.parent.dpla.enable_for_palette(palid) else: # Doesn't have self.parent.dpla.disable_for_palette(palid) for cidx in range(0, 16): try: time = int( self.parent.builder.get_object( f'palette_animation{aidx}_frame_time{cidx}'). get_text()) except: time = 0 had_errors = True self.parent.dpla.durations_per_frame_for_colors[ offset + cidx] = time if had_errors: md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.WARNING, Gtk.ButtonsType.OK, _("Some values were invalid (not a number). " "They were replaced with 0."), title=_("Warning!")) md.set_position(Gtk.WindowPosition.CENTER) md.run() md.destroy() self.parent.reload_all() self.parent.mark_as_modified()
def on_export_clicked(self, w: Gtk.MenuToolButton): self.img.palettes = make_palette_colors_unique(self.img.palettes) md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("This will export the currently selected image with the currently selected palette. " "The image file itself contains all palettes, you can choose to import the edited palettes on import."), title=_("Export Images") ) md.run() md.destroy() dialog = Gtk.FileChooserNative.new( _("Export current image to folder..."), MainController.window(), Gtk.FileChooserAction.SAVE, _('_Save'), None ) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: fn = add_extension_if_missing(fn, 'png') self.img.to_pil(self.image_idx, self.palette_idx).save(fn)
def on_btn_export_clicked(self, *args): md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.MODAL, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("Export is done to a CSV file with the following specifications:\n" "- Contains all strings in order, one per row\n" "- Strings may be quoted with: \" and escaped with doube-quotes." )) md.run() md.destroy() save_diag = Gtk.FileChooserNative.new(_("Export strings as..."), MainController.window(), Gtk.FileChooserAction.SAVE, None, None) add_dialog_csv_filter(save_diag) response = save_diag.run() fn = save_diag.get_filename() save_diag.destroy() if response == Gtk.ResponseType.ACCEPT: if '.' not in fn: fn += '.csv' with open_utf8(fn, 'w') as result_file: wr = csv.writer(result_file) wr.writerows([[x] for x in self._str.strings])
def on_men_map_export_activate(self): dialog: Gtk.Dialog = self.parent.builder.get_object( 'dialog_map_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 PNGs of map...", MainController.window(), Gtk.FileChooserAction.SELECT_FOLDER, "_Save", None) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: base_filename = os.path.join( fn, f'{self.parent.module.bgs.level[self.parent.item_id].bma_name}_layer' ) layer1 = self.parent.bma.to_pil_single_layer( self.parent.bpc, self.parent.bpl.palettes, self.parent.bpas, 0) layer1.save(base_filename + '1.png') if self.parent.bma.number_of_layers > 1: layer2 = self.parent.bma.to_pil_single_layer( self.parent.bpc, self.parent.bpl.palettes, self.parent.bpas, 2) layer2.save(base_filename + '2.png')
def _import_tiles(self, layer): dialog: Gtk.Dialog = self.parent.builder.get_object( 'dialog_tiles_import') dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) # Set dialog settings to map settings tiles_import_file: Gtk.FileChooserButton = self.parent.builder.get_object( 'tiles_import_file') tiles_import_file.unselect_all() resp = dialog.run() dialog.hide() if resp == ResponseType.OK: try: if tiles_import_file.get_filename() is None: md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "An image must be selected.", title="Error!") md.set_position(Gtk.WindowPosition.CENTER) md.run() md.destroy() else: with open(tiles_import_file.get_filename(), 'rb') as f: self.parent.bpc.pil_to_tiles(layer, Image.open(f)) except Exception as err: display_error(sys.exc_info(), str(err)) self.parent.reload_all() self.parent.mark_as_modified()
def on_men_palettes_ani_edit_activate(self): if not self.parent.bpl.has_palette_animation: md = SkyTempleMessageDialog(MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "Palette Animation is not enabled.", title="Warning!") md.set_position(Gtk.WindowPosition.CENTER) md.run() md.destroy() return # This is controlled by a separate controller dict_pals = OrderedDict() for i, pal in enumerate(self.parent.bpl.animation_palette): dict_pals[f'F{i + 1}'] = pal.copy() cntrl = PaletteEditorController(MainController.window(), dict_pals, False, True, False) edited_palettes = cntrl.show() if edited_palettes: self.parent.bpl.animation_palette = edited_palettes self.parent.reload_all() self.parent.mark_as_modified() del cntrl
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_item_categories_add_clicked(self, *args): store: Gtk.Store = self.builder.get_object('item_categories_store') dialog: Gtk.Dialog = self.builder.get_object('dialog_category_add') dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) # Init available categories cb_store: Gtk.ListStore = self.builder.get_object('category_add_store') cb: Gtk.ComboBoxText = self.builder.get_object('category_add_cb') available_categories = self._fill_available_categories_into_store( cb_store) # Show error if no categories available if len(available_categories) < 1: display_error(None, 'All categories are already in the list.', 'Can not add category') return cb.set_active_iter(cb_store.get_iter_first()) resp = dialog.run() dialog.hide() if resp == Gtk.ResponseType.APPLY: row = cb_store[cb.get_active_iter()] store.append([row[0], row[1], False, "0%", "0"]) self._save_item_spawn_rates() self._update_cr_item_cat_name_store()
def on_btn_add_clicked(self, widget): dialog: Gtk.Dialog = self.builder.get_object('dialog_choose_char') self.builder.get_object('entry_char_id').set_text(str(0)) self.builder.get_object('entry_char_id').set_increments(1,1) self.builder.get_object('entry_char_id').set_range(0, 255) dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) resp = dialog.run() dialog.hide() if resp == ResponseType.OK: cb_store: Gtk.ListStore = self.builder.get_object('table_store') cb: Gtk.ComboBoxText = self.builder.get_object('cb_table_select') v : int = cb_store[cb.get_active_iter()][0] char = int(self.builder.get_object('entry_char_id').get_text()) try: for e in self.entries: if e.get_properties()["char"]==char: raise ValueError(f"Character {char} already exists in the table!") entry = self.font.create_entry_for_table(v) entry.set_properties({"char": char}) self.entries.append(entry) entry_tree: Gtk.TreeView = self.builder.get_object('entry_tree') store: Gtk.ListStore = entry_tree.get_model() self._add_property_row(store, entry) self.module.mark_font_as_modified(self.spec) except Exception as err: display_error( sys.exc_info(), str(err), "Error adding character." )
def on_import_attack_clicked(self, w: Gtk.MenuToolButton): sprite = self.module.import_a_sprite() if sprite is None: return self.module.save_monster_attack_sprite(self.item_id, sprite, raw=True) self._mark_as_modified_cb() MainController.reload_view()
def on_men_chunks_layer1_export_activate(self): dialog: Gtk.Dialog = self.parent.builder.get_object( 'dialog_chunks_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 chunks...", 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.dpc.chunks_to_pil(self.parent.dpci, self.parent.dpl.palettes, 16).save(fn) except BaseException as err: display_error(sys.exc_info(), str(err), "Error exporting the tileset.")
def on_men_tiles_ani_export_activate(self): dialog: Gtk.Dialog = self.parent.builder.get_object( 'dialog_tiles_animated_export') dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) cb: Gtk.ComboBox = self.parent.builder.get_object( 'dialog_tiles_animated_export_select_bpa') store = Gtk.ListStore(str, int) label_sep: Gtk.Label = self.parent.builder.get_object( 'dialog_tiles_animated_export_label_sep') label_sep.set_text(label_sep.get_text().replace( '@@@name_pattern@@@', self._get_bpa_export_name_pattern('X', 'Y'))) for i, bpa in enumerate(self.parent.bpas): if bpa is not None: store.append([f'BPA{i+1}', i]) cb.set_model(store) cell = Gtk.CellRendererText() cb.pack_start(cell, True) cb.add_attribute(cell, 'text', 0) cb.set_active(0) dialog.run() # The dialog has two buttons with separate connected signals ( # on_dialog_tiles_animated_export_export_btn_activate, on_dialog_tiles_animated_export_import_btn_activate # ) dialog.hide()
def on_men_palettes_ani_settings_activate(self): dialog: Gtk.Dialog = self.parent.builder.get_object( 'dialog_palettes_animated_settings') dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) self.parent.builder.get_object( 'palette_animation11_enabled').set_active( self.parent.dpla.has_for_palette(0)) self.parent.builder.get_object( 'palette_animation12_enabled').set_active( self.parent.dpla.has_for_palette(1)) self.parent.builder.get_object( f'palette_animation11_frame_time').set_text( str(self.parent.dpla.get_duration_for_palette(0))) self.parent.builder.get_object( f'palette_animation12_frame_time').set_text( str(self.parent.dpla.get_duration_for_palette(1))) response = dialog.run() dialog.hide() if response == Gtk.ResponseType.OK: had_errors = False for palid, enabled, frame_time in ( (0, 'palette_animation11_enabled', 'palette_animation11_frame_time'), (1, 'palette_animation12_enabled', 'palette_animation12_frame_time')): if self.parent.builder.get_object(enabled).get_active(): # Has palette animations! self.parent.dpla.enable_for_palette(palid) else: # Doesn't have self.parent.dpla.disable_for_palette(palid) try: time = int( self.parent.builder.get_object(frame_time).get_text()) except: time = 0 had_errors = True self.parent.dpla.set_duration_for_palette(palid, time) if had_errors: md = Gtk.MessageDialog( MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.WARNING, Gtk.ButtonsType.OK, "Some values were invalid (not a number). " "They were replaced with 0.", title="Warning!") md.set_position(Gtk.WindowPosition.CENTER) md.run() md.destroy() self.parent.reload_all() self.parent.mark_as_modified()
def on_btn_add_clicked(self, *args): from skytemple.module.map_bg.module import MAP_BG_PATH response, name = self._show_generic_input(_('Map Background Name'), _('Create Background')) if response != Gtk.ResponseType.OK: return name = name.lower() name_bg_list = name.upper() if len(name) < 1 or len(name) > 8: md = SkyTempleMessageDialog( SkyTempleMainController.window(), Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, _("The length of the map background name must be between 1-8 characters." )) md.run() md.destroy() return bpl_name = f'{name}.bpl' bpc_name = f'{name}.bpc' bma_name = f'{name}.bma' if self.module.project.file_exists(MAP_BG_PATH + bpl_name) or \ self.module.project.file_exists(MAP_BG_PATH + bpc_name) or \ self.module.project.file_exists(MAP_BG_PATH + bma_name): md = SkyTempleMessageDialog( SkyTempleMainController.window(), Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, _("A map background with this name already exists.")) md.run() md.destroy() return with open(os.path.join(data_dir(), 'empty.bpl'), 'rb') as f: empty_bpl = FileType.BPL.deserialize(f.read()) with open(os.path.join(data_dir(), 'empty.bma'), 'rb') as f: empty_bma = FileType.BMA.deserialize(f.read()) with open(os.path.join(data_dir(), 'empty.bpc'), 'rb') as f: empty_bpc = FileType.BPC.deserialize(f.read()) # Write to ROM self.module.project.create_new_file(MAP_BG_PATH + bpl_name, empty_bpl, FileType.BPL) self.module.project.create_new_file(MAP_BG_PATH + bma_name, empty_bma, FileType.BMA) self.module.project.create_new_file(MAP_BG_PATH + bpc_name, empty_bpc, FileType.BPC) self.module.add_map(name_bg_list) md = SkyTempleMessageDialog(SkyTempleMainController.window(), Gtk.DialogFlags.MODAL, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("Map background added successfully"), is_success=True) md.run() md.destroy()
def on_separate_import_activate(self, *args): md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, f( _("To import, select a directory to import from. Files with the pattern '{self.item_id + 1}_XX.png'\n" "will be imported, where XX is a number between 0 and 40.")), title=_("Import Portraits")) md.run() md.destroy() dialog = Gtk.FileChooserNative.new(_("Import portraits from PNGs..."), MainController.window(), Gtk.FileChooserAction.SELECT_FOLDER, None, None) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: r = re.compile(rf"{self.item_id + 1}_(\d+)\.png", re.IGNORECASE) imgs = { int(match[1]): name for match, name in self._try_match_import(r, os.listdir(fn)) if match is not None and int(match[1]) <= 40 } for subindex, image_fn in imgs.items(): try: with open(os.path.join(fn, image_fn), 'rb') as f: image = Image.open(f) 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(_(f"Error for '{name}'."))) # 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_men_map_import_activate(self): dialog: Gtk.Dialog = self.parent.builder.get_object( 'dialog_map_import') dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) # Set dialog settings to map settings map_import_layer1_file: Gtk.FileChooserButton = self.parent.builder.get_object( 'map_import_layer1_file') map_import_layer2_file: Gtk.FileChooserButton = self.parent.builder.get_object( 'map_import_layer2_file') map_import_layer1_file.unselect_all() map_import_layer2_file.unselect_all() if self.parent.bma.number_of_layers < 2: map_import_layer2_file.set_sensitive(False) resp = dialog.run() dialog.hide() if resp == ResponseType.OK: try: img1_path = map_import_layer1_file.get_filename() img2_path = map_import_layer2_file.get_filename() palettes_from_lower_layer = self.parent.builder.get_object( 'dialog_map_import_palette_config').get_value() if self.parent.bma.number_of_layers < 2 and img1_path is not None: with open(img1_path, 'rb') as f: self.parent.bma.from_pil(self.parent.bpc, self.parent.bpl, Image.open(f), None, True) elif img1_path is not None and img2_path is None: with open(img1_path, 'rb') as f1: self.parent.bma.from_pil(self.parent.bpc, self.parent.bpl, Image.open(f1), None, True) elif img1_path is None and img2_path is not None: with open(img2_path, 'rb') as f2: self.parent.bma.from_pil(self.parent.bpc, self.parent.bpl, None, Image.open(f2), True) elif img1_path is not None and img2_path is not None: with open(img1_path, 'rb') as f1: with open(img2_path, 'rb') as f2: self.parent.bma.from_pil( self.parent.bpc, self.parent.bpl, Image.open(f1), Image.open(f2), True, how_many_palettes_lower_layer=int( palettes_from_lower_layer)) except Exception as err: display_error(sys.exc_info(), str(err)) self.parent.reload_all() self.parent.mark_as_modified()
def _run_window(self): dialog: Gtk.Dialog = self.builder.get_object('dialog') dialog.resize(750, 350) dialog.set_transient_for(MainController.window()) dialog.set_attached_to(MainController.window()) self.buffer.delete(self.buffer.get_start_iter(), self.buffer.get_end_iter()) self._update_status(GfxcrunchStatus.RUNNING) self.builder.get_object('spinner').start() self.builder.get_object('close').set_sensitive(False) dialog.run() dialog.hide()
def _setup_dialog(self): dialog: Gtk.Dialog = self.builder.get_object('dialog_add_remove') self.builder.get_object('id_key_add_remove').set_increments(1, 1) self.builder.get_object('id_key_add_remove').set_range( 0, self._get_max_key()) self.builder.get_object('id_key_add_remove').set_text(str(0)) dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) return dialog
def on_import_clicked(self, w: Gtk.MenuToolButton): md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("To import, select a folder containing all the files that were created when exporting the font.\n" "IMPORTANT: All image files must be indexed PNGs and use the same palette!" ), title=_("Import Font")) md.run() md.destroy() fdialog = Gtk.FileChooserNative.new( _("Import font from folder..."), MainController.window(), Gtk.FileChooserAction.SELECT_FOLDER, None, None) response = fdialog.run() fn = fdialog.get_filename() fdialog.destroy() if response == Gtk.ResponseType.ACCEPT: assert self.builder dialog: Gtk.Dialog = self.builder.get_object('dialog_import') self.builder.get_object('nb_entries_import').set_increments(1, 1) self.builder.get_object('nb_entries_import').set_range( 1, MAX_ENTRIES - 1) self.builder.get_object('nb_entries_import').set_text( str(self.font.get_nb_entries())) # type: ignore dialog.set_attached_to(MainController.window()) dialog.set_transient_for(MainController.window()) resp = dialog.run() dialog.hide() if resp == Gtk.ResponseType.OK: try: lst_entries: List[Optional[Image.Image]] = [] for i in range( int( self.builder.get_object( 'nb_entries_import').get_text())): path = os.path.join(fn, f'{i:0>4}.png') if os.path.exists(path): lst_entries.append(Image.open(path, 'r')) else: lst_entries.append(None) self.font.set_entries(lst_entries) # type: ignore self.module.mark_font_as_modified(self.spec) except Exception as err: display_error(sys.exc_info(), str(err), _("Error importing font.")) self._init_font()
def do_import(self, item_id: int, cb=lambda: None): is_zip = self._zip_is_active() dialog = Gtk.FileChooserNative.new( _("Import spritesheet..."), MainController.window(), Gtk.FileChooserAction.SELECT_FOLDER if not is_zip else Gtk.FileChooserAction.OPEN, None, None) if is_zip: self._add_zip_filter_to_dialog(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: try: wan = FileType.WAN.CHARA.import_sheets(fn) if not is_zip \ else FileType.WAN.CHARA.import_sheets_from_zip(fn) monster, ground, attack = FileType.WAN.CHARA.split_wan(wan) md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("The spritesheet was successfully imported."), title=_("Success!"), is_success=True) md.run() md.destroy() self.module.save_monster_monster_sprite(item_id, monster) self.module.save_monster_ground_sprite(item_id, ground) self.module.save_monster_attack_sprite(item_id, attack) # Shadow size if not is_zip: tree = ElementTree.parse(os.path.join( fn, 'AnimData.xml')).getroot() else: with ZipFile(fn, 'r') as ZipObj: tree = ElementTree.fromstring( ZipObj.read('AnimData.xml')) self._set_shadow_size_cb(int( tree.find('ShadowSize').text)) # type: ignore cb() self._mark_as_modified_cb() MainController.reload_view() except BaseException as e: display_error(sys.exc_info(), str(e), _("Error importing the spritesheet."))
def on_export_clicked(self, w: Gtk.MenuToolButton): is_zip = self._zip_is_active() dialog = Gtk.FileChooserNative.new( _("Export spritesheet..."), MainController.window(), Gtk.FileChooserAction.SELECT_FOLDER if not is_zip else Gtk.FileChooserAction.SAVE, _('_Save'), None) if is_zip: self._add_zip_filter_to_dialog(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: try: monster: WanFile = self.module.get_monster_monster_sprite_chara( self.item_id) # type: ignore ground: WanFile = self.module.get_monster_ground_sprite_chara( self.item_id) # type: ignore attack: WanFile = self.module.get_monster_attack_sprite_chara( self.item_id) # type: ignore merged = FileType.WAN.CHARA.merge_wan(monster, ground, attack) merged.sdwSize = self._get_shadow_size_cb() try: animation_names = self.module.project.get_rom_module( ).get_static_data().animation_names[self.item_id] except KeyError: # Fall back to Bulbasaur animation_names = self.module.project.get_rom_module( ).get_static_data().animation_names[0] if not is_zip: FileType.WAN.CHARA.export_sheets(fn, merged, animation_names) else: FileType.WAN.CHARA.export_sheets_as_zip( fn, merged, animation_names) md = SkyTempleMessageDialog( MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("The spritesheet was successfully exported."), title=_("Success!"), is_success=True) md.run() md.destroy() except BaseException as e: display_error(sys.exc_info(), str(e), _("Error exporting the spritesheet."))
def on_btn_import_clicked(self, *args): md = SkyTempleMessageDialog(MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("To import select the XML file in the DTEF tileset package. If it " "is still zipped, unzip it first."), title="SkyTemple") md.run() md.destroy() dialog = Gtk.FileChooserNative.new( _("Import dungeon tileset..."), MainController.window(), Gtk.FileChooserAction.OPEN, None, None ) filter = Gtk.FileFilter() filter.set_name(_("DTEF XML document (*.dtef.xml)")) filter.add_pattern("*.dtef.xml") dialog.add_filter(filter) add_dialog_xml_filter(dialog) response = dialog.run() fn = dialog.get_filename() dialog.destroy() if response == Gtk.ResponseType.ACCEPT: try: dirname = os.path.dirname(fn) fn_xml = fn fn_var0 = os.path.join(dirname, VAR0_FN) fn_var1 = os.path.join(dirname, VAR1_FN) fn_var2 = os.path.join(dirname, VAR2_FN) dtef_importer = ExplorersDtefImporter(self.dma, self.dpc, self.dpci, self.dpl, self.dpla) dtef_importer.do_import( dirname, fn_xml, fn_var0, fn_var1, fn_var2 ) md = SkyTempleMessageDialog(MainController.window(), Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _("The tileset was successfully imported."), title=_("Success!"), is_success=True) md.run() md.destroy() self.mark_as_modified() MainController.reload_view() except BaseException as e: display_error( sys.exc_info(), str(e), _("Error importing the tileset.") )
def collect_state_context() -> Dict[str, 'Captured']: from skytemple.controller.main import MainController from skytemple.core.rom_project import RomProject from skytemple_files.common.util import capture_any rom_project = RomProject.get_current() try: view_state = MainController._instance._current_view_module.collect_debugging_info( # type: ignore MainController._instance._current_view_controller # type: ignore ) if "models" in view_state: # type: ignore view_state["models"] = { k: capture_any(v) for k, v in view_state["models"].items() } # type: ignore except Exception as ex: view_state = {"error_collecting": str(ex)} w, h = MainController.window().get_size() dw = if_not_none(MainController.debugger_manager()._opened_main_window, lambda w: w.get_size()[0]) dh = if_not_none(MainController.debugger_manager()._opened_main_window, lambda w: w.get_size()[1]) return { "skytemple": { "window": { "width": w, "height": h, }, "rom": { "filename": if_not_none(rom_project, lambda p: p.get_rom_name()), "edition": if_not_none(rom_project, lambda p: p.get_rom_module().get_static_data()), }, "module": type(MainController._instance._current_view_module).__qualname__, "view": MainController._instance._current_view_controller_class. __qualname__, # type: ignore "view_state": view_state }, "ssb_debugger": { "window": { "width": dw, "height": dh, }, "open_scripts": debugger_open_scripts(MainController.debugger_manager()), "focused_script": debugger_focused_script(MainController.debugger_manager()), #"emulator_state": debugger_emulator_state(MainController.debugger_manager()) } }
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_btn_import_clicked(self, *args): save_diag = Gtk.FileChooserNative.new(_("Import Pokémon from..."), SkyTempleMainController.window(), Gtk.FileChooserAction.OPEN, None, None) add_dialog_xml_filter(save_diag) response = save_diag.run() fn = save_diag.get_filename() save_diag.destroy() if response == Gtk.ResponseType.ACCEPT: self.module.import_from_xml([self.entry.md_index], ElementTree.parse(fn).getroot()) SkyTempleMainController.reload_view()