Beispiel #1
0
 def get_dummy_tileset(self) -> [Dma, Image.Image]:
     with open(os.path.join(data_dir(), 'fixed_floor', 'dummy.dma'),
               'rb') as f:
         dma = FileType.DMA.deserialize(f.read())
     return (dma,
             Image.open(os.path.join(data_dir(), 'fixed_floor',
                                     'dummy.png')))
Beispiel #2
0
 def _load_support_images(self):
     # Load the support us images
     try:
         # Discord
         image = Gtk.Image()
         image.show()
         image.set_from_file(os.path.join(data_dir(), "discord.png"))
         self.builder.get_object('suppot_us_discord_container').add(image)
         # Github
         image = Gtk.Image()
         image.show()
         image.set_from_file(os.path.join(data_dir(), "github.png"))
         self.builder.get_object('suppot_us_github_container').add(image)
         # Kofi
         image = Gtk.Image()
         image.show()
         image.set_from_file(os.path.join(data_dir(), "kofi.png"))
         self.builder.get_object('suppot_us_kofi_parakoopa_container').add(image)
         # Kofi 2
         image = Gtk.Image()
         image.show()
         image.set_from_file(os.path.join(data_dir(), "kofi.png"))
         self.builder.get_object('suppot_us_kofi_psy_container').add(image)
     except BaseException:
         # We are not crashing over some images...
         pass
 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')))
Beispiel #4
0
    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()
Beispiel #5
0
 def _load_support_images(self):
     # Load the Discord badge
     try:
         raise Exception("Disabled for now.")
         url = 'https://raster.shields.io/discord/710190644152369162?label=Discord'
         req = urllib.request.Request(url,
                                      headers={'User-Agent': 'Mozilla/5.0'})
         # Some weird issue on Windows with PyInstaller...:
         ctx = ssl.create_default_context()
         ctx.check_hostname = False
         ctx.verify_mode = ssl.CERT_NONE
         input_stream = Gio.MemoryInputStream.new_from_data(
             urllib.request.urlopen(req, context=ctx, timeout=1).read(),
             None)
         pixbuf = Pixbuf.new_from_stream(input_stream, None)
         image = Gtk.Image()
         image.show()
         image.set_from_pixbuf(pixbuf)
         self.builder.get_object('discord_icon_container').add(image)
     except BaseException:
         # We are not crashing over a Discord badge...
         logger.error("Failed loading the Discord badge.",
                      exc_info=sys.exc_info())
     # Load the support us images
     try:
         # Discord
         image = Gtk.Image()
         image.show()
         image.set_from_file(os.path.join(data_dir(), "discord.png"))
         self.builder.get_object('suppot_us_discord_container').add(image)
         # Github
         image = Gtk.Image()
         image.show()
         image.set_from_file(os.path.join(data_dir(), "github.png"))
         self.builder.get_object('suppot_us_github_container').add(image)
         # Kofi
         image = Gtk.Image()
         image.show()
         image.set_from_file(os.path.join(data_dir(), "kofi.png"))
         self.builder.get_object('suppot_us_kofi_parakoopa_container').add(
             image)
         # Kofi 2
         image = Gtk.Image()
         image.show()
         image.set_from_file(os.path.join(data_dir(), "kofi.png"))
         self.builder.get_object('suppot_us_kofi_psy_container').add(image)
     except BaseException:
         # We are not crashing over some images...
         pass
Beispiel #6
0
    def __init__(self, project: 'RomProject'):
        self._project = project
        self._loader_surface_dims: Optional[Tuple[int, int]] = None
        self._loader_surface: Optional[cairo.ImageSurface] = None

        self._loaded__monsters: Dict[ActorSpriteKey,
                                     SpriteAndOffsetAndDims] = {}
        self._loaded__monsters_outlines: Dict[ActorSpriteKey,
                                              SpriteAndOffsetAndDims] = {}
        self._loaded__actor_placeholders: Dict[ActorSpriteKey,
                                               SpriteAndOffsetAndDims] = {}
        self._loaded__objects: Dict[str, SpriteAndOffsetAndDims] = {}
        self._loaded__traps: Dict[int, SpriteAndOffsetAndDims] = {}
        self._loaded__items: Dict[int, SpriteAndOffsetAndDims] = {}

        self._requests__monsters: List[ActorSpriteKey] = []
        self._requests__monsters_outlines: List[ActorSpriteKey] = []
        self._requests__actor_placeholders: List[ActorSpriteKey] = []
        self._requests__objects: List[str] = []
        self._requests__traps: List[int] = []
        self._requests__items: List[int] = []

        self._monster_md: ModelContext[Md] = self._project.open_file_in_rom(
            MONSTER_MD, FileType.MD, threadsafe=True)
        self._monster_bin: ModelContext[
            BinPack] = self._project.open_file_in_rom(MONSTER_BIN,
                                                      FileType.BIN_PACK,
                                                      threadsafe=True)
        self._dungeon_bin: Optional[ModelContext[DungeonBinPack]] = None

        self._stripes = Image.open(os.path.join(data_dir(), 'stripes.png'))
        self._loaded_standins: Optional[Dict[int, int]] = None
    def __init__(self, project: 'RomProject'):
        self._project = project
        self._loader_surface_dims = None
        self._loader_surface = None

        self._loaded__monsters: Dict[ActorSpriteKey,
                                     SpriteAndOffsetAndDims] = {}
        self._loaded__monsters_outlines: Dict[ActorSpriteKey,
                                              SpriteAndOffsetAndDims] = {}
        self._loaded__actor_placeholders: Dict[ActorSpriteKey,
                                               SpriteAndOffsetAndDims] = {}
        self._loaded__objects: Dict[str, SpriteAndOffsetAndDims] = {}

        self._requests__monsters: List[ActorSpriteKey] = []
        self._requests__monsters_outlines: List[ActorSpriteKey] = []
        self._requests__actor_placeholders: List[ActorSpriteKey] = []
        self._requests__objects: List[str] = []

        self._monster_md: Md = self._project.open_file_in_rom(MONSTER_MD,
                                                              FileType.MD,
                                                              threadsafe=True)
        self._monster_bin: BinPack = self._project.open_file_in_rom(
            MONSTER_BIN, FileType.BIN_PACK, threadsafe=True)

        self._stripes = Image.open(os.path.join(data_dir(), 'stripes.png'))
        self._loaded_standins = None
Beispiel #8
0
    def is_available(self):
        if not ENABLE_GFXCRUNCH:
            return False

        path = os.path.join(data_dir(), GFXCRUNCH_BIN)
        if not os.path.exists(path):
            return False

        if not sys.platform.startswith('win'):
            if which(WINE_BIN) is None:
                return False

        return True
 def process(self):
     # BPC:
     start_offset = self.bpc.layers[0].chunk_tilemap_len
     with open(os.path.join(data_dir(), 'created_with.png'), 'rb') as f:
         palettes = self._import_to_bpc(0, Image.open(f))
     # BMA:
     for x in range(0, 11):
         for y in range(0, 8):
             index = y * 11 + x % 11 + start_offset
             if index == 0:
                 index = 1
             self.bma.place_chunk(0, x + 11, y, index)
     # BPL:
     self.bpl.palettes[6:14] = palettes[0:8]
Beispiel #10
0
    def on_btn_add_clicked(self, *args):
        from skytemple.module.sprite.module import GROUND_DIR, WAN_FILE_EXT
        response, name = self._show_generic_input(_('Sprite Name'),
                                                  _('Create Object Sprite'))
        if response != Gtk.ResponseType.OK:
            return
        name = name.lower()
        if len(name) < 1 or len(name) > 10:
            md = SkyTempleMessageDialog(
                SkyTempleMainController.window(), Gtk.DialogFlags.MODAL,
                Gtk.MessageType.ERROR, Gtk.ButtonsType.OK,
                _("The length of the sprite name must be between 1-10 characters."
                  ))
            md.run()
            md.destroy()
            return
        obj_name = f'{GROUND_DIR}/{name}.{WAN_FILE_EXT}'
        if self.module.project.file_exists(obj_name):
            md = SkyTempleMessageDialog(
                SkyTempleMainController.window(), Gtk.DialogFlags.MODAL,
                Gtk.MessageType.ERROR, Gtk.ButtonsType.OK,
                _("A sprite with this name already exists."))
            md.run()
            md.destroy()
            return

        with open(os.path.join(data_dir(), 'empty.wan'), 'rb') as f:
            empty_wan = f.read()

        # Write to ROM
        self.module.project.create_file_manually(obj_name, empty_wan)
        self.module.add_wan(f'{name}.{WAN_FILE_EXT}')

        md = SkyTempleMessageDialog(SkyTempleMainController.window(),
                                    Gtk.DialogFlags.MODAL,
                                    Gtk.MessageType.INFO,
                                    Gtk.ButtonsType.OK,
                                    _("Object sprite added successfully"),
                                    is_success=True)
        md.run()
        md.destroy()
Beispiel #11
0
    def __init__(self, parent: Gtk.Window, dialog_flags: Gtk.DialogFlags,
                 message_type: Gtk.MessageType, buttons_type: Gtk.ButtonsType,
                 *args, **kwargs):
        img = IMGS[message_type]
        if IS_SUCCESS in kwargs:
            if kwargs[IS_SUCCESS]:
                img = IMG_HAPPY
            del kwargs[IS_SUCCESS]
        self.img: Gtk.Image = Gtk.Image.new_from_file(
            os.path.join(data_dir(), img))
        super().__init__(parent, dialog_flags, message_type, buttons_type,
                         *args, **kwargs)

        box: Gtk.Box = self.get_message_area()
        parent: Gtk.Box = box.get_parent()
        box.set_valign(Gtk.Align.CENTER)

        parent.pack_start(self.img, False, False, 0)
        parent.pack_start(box, False, False, 0)

        parent.child_set_property(self.img, 'position', 0)
        self.img.show()
Beispiel #12
0
 def get_gfxcrunch_cmd(self) -> Tuple[str, List[str], bool]:
     """Returns the CMD for gfxcrunch and the base argument list and if shell=True"""
     if sys.platform.startswith('win'):
         return os.path.join(data_dir(), GFXCRUNCH_BIN), [], False
     return WINE_BIN, [os.path.join(data_dir(), GFXCRUNCH_BIN)], False
Beispiel #13
0
 def _get_empty_scene(self) -> Ssa:
     with open(os.path.join(data_dir(), 'empty.ssx'), 'rb') as f:
         return FileType.SSA.deserialize(f.read())
Beispiel #14
0
def main():
    # TODO: Gtk.Application: https://python-gtk-3-tutorial.readthedocs.io/en/latest/application.html
    path = os.path.abspath(os.path.dirname(__file__))

    # Load settings
    settings = SkyTempleSettingsStore()

    if sys.platform.startswith('win'):
        # Load theming under Windows
        _load_theme(settings)
        # Solve issue #12
        try:
            from skytemple_files.common.platform_utils.win import win_set_error_mode
            win_set_error_mode()
        except BaseException:
            # This really shouldn't fail, but it's not important enough to crash over
            pass

    if sys.platform.startswith('darwin'):
        # Load theming under macOS
        _load_theme(settings)

        # The search path is wrong if SkyTemple is executed as an .app bundle
        if getattr(sys, 'frozen', False):
            path = os.path.dirname(sys.executable)

    if sys.platform.startswith('linux') and gdk_backend() == GDK_BACKEND_BROADWAY:
        gtk_settings = Gtk.Settings.get_default()
        gtk_settings.set_property("gtk-theme-name", 'Arc-Dark')
        gtk_settings.set_property("gtk-application-prefer-dark-theme", True)

    itheme: Gtk.IconTheme = Gtk.IconTheme.get_default()
    itheme.append_search_path(os.path.abspath(icons()))
    itheme.append_search_path(os.path.abspath(os.path.join(data_dir(), "icons")))
    itheme.append_search_path(os.path.abspath(os.path.join(get_debugger_data_dir(), "icons")))
    itheme.rescan_if_needed()

    # Load Builder and Window
    builder = make_builder(os.path.join(path, "skytemple.glade"))
    main_window: Window = builder.get_object("main_window")
    main_window.set_role("SkyTemple")
    GLib.set_application_name("SkyTemple")
    GLib.set_prgname("skytemple")
    # TODO: Deprecated but the only way to set the app title on GNOME...?
    main_window.set_wmclass("SkyTemple", "SkyTemple")

    # Load CSS
    style_provider = Gtk.CssProvider()
    with open(os.path.join(path, "skytemple.css"), 'rb') as f:
        css = f.read()
    style_provider.load_from_data(css)
    Gtk.StyleContext.add_provider_for_screen(
        Gdk.Screen.get_default(), style_provider,
        Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
    )

    # Load async task runner thread
    AsyncTaskRunner.instance()

    # Init. core events
    event_manager = EventManager.instance()
    if settings.get_integration_discord_enabled():
        try:
            from skytemple.core.events.impl.discord import DiscordPresence
            discord_listener = DiscordPresence()
            event_manager.register_listener(discord_listener)
        except BaseException:
            pass

    # Load modules
    Modules.load()

    # Load main window + controller
    MainController(builder, main_window, settings)

    main_window.present()
    main_window.set_icon_name('skytemple')
    try:
        Gtk.main()
    except (KeyboardInterrupt, SystemExit):
        AsyncTaskRunner.end()
Beispiel #15
0
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with SkyTemple.  If not, see <https://www.gnu.org/licenses/>.
import logging
import os
import sys
import locale
import gettext
from skytemple.core.ui_utils import data_dir, APP, gdk_backend, GDK_BACKEND_BROADWAY

# Setup locale :(
from skytemple.core.settings import SkyTempleSettingsStore
LOCALE_DIR = os.path.abspath(os.path.join(data_dir(), 'locale'))
settings = SkyTempleSettingsStore()
if hasattr(locale, 'bindtextdomain'):
    libintl = locale
elif sys.platform.startswith('win'):
    import ctypes
    import ctypes.util
    if os.getenv('LANG') is None:
        lang, enc = locale.getdefaultlocale()
        os.environ['LANG'] = lang
        ctypes.cdll.msvcrt._putenv ("LANG=" + lang)
    libintl_loc = os.path.join(os.path.dirname(__file__), 'libintl-8.dll')
    if os.path.exists(libintl_loc):
        libintl = ctypes.cdll.LoadLibrary(libintl_loc)
    else:
        libintl = ctypes.cdll.LoadLibrary(ctypes.util.find_library('libintl-8'))
Beispiel #16
0
 def _update_status(self, status):
     self.status = status
     img: Gtk.Image = self.builder.get_object('duskako')
     img.set_from_file(os.path.join(data_dir(), IMGS[status]))