First implementation of lazy-loading tab groups
This commit is contained in:
parent
44d54b0939
commit
55e8802835
369
ff5reader.py
369
ff5reader.py
|
@ -18,8 +18,9 @@
|
|||
|
||||
import sys
|
||||
import re
|
||||
from struct import unpack
|
||||
import time
|
||||
from functools import cached_property
|
||||
from struct import unpack
|
||||
from typing import Iterable
|
||||
|
||||
from includes.helpers import *
|
||||
|
@ -33,6 +34,7 @@ from includes.snestile import (
|
|||
)
|
||||
from includes.snes import *
|
||||
import includes.ff5.const as const
|
||||
from includes.ff5.files import ROM_RPGe, ROM_SNES
|
||||
from includes.ff5.strings import StringBlock, RPGe_Dialogue_Width
|
||||
from includes.ff5.strings import Strings as FFVStrings
|
||||
import includes.ff5.structs as FFVStructs
|
||||
|
@ -49,102 +51,122 @@ class FF5Reader(QMainWindow):
|
|||
'''
|
||||
Main GUI class
|
||||
'''
|
||||
def __init__(self):
|
||||
QMainWindow.__init__(self, None)
|
||||
perfcount()
|
||||
print('Reading ROMs')
|
||||
ROM_en = ff5.files.ROM_RPGe
|
||||
ROM_jp = ff5.files.ROM_SNES
|
||||
ROM_FF4jp = load_raw(filename_jp_ff4)
|
||||
ROM_FF6jp = load_raw(filename_jp_ff6)
|
||||
print(len(ROM_FF4jp), filename_jp_ff4)
|
||||
print(len(ROM_FF6jp), filename_jp_ff6)
|
||||
perfcount()
|
||||
|
||||
print('Generating Glyphs')
|
||||
self.glyph_sprites = {
|
||||
'glyphs_en_s': generate_glyphs(ROM_en, 0x11F000),
|
||||
'glyphs_en_l': generate_glyphs_large(ROM_en, 0x03E800),
|
||||
'glyphs_jp_s': generate_glyphs(ROM_jp, 0x11F000),
|
||||
'glyphs_jp_l': generate_glyphs_large(ROM_jp, 0x03E800),
|
||||
'glyphs_kanji': generate_glyphs_large(ROM_jp, 0x1BD000, 0x1AA), # Kanji are unchanged in EN version
|
||||
@cached_property
|
||||
def battle_strips_ff4(self):
|
||||
return ff4.make_character_battle_sprites(self.ROM_FF4jp)
|
||||
|
||||
@cached_property
|
||||
def field_strips_ff4(self):
|
||||
return ff4.make_character_field_sprites(self.ROM_FF4jp)
|
||||
|
||||
@cached_property
|
||||
def portraits_ff4(self):
|
||||
return ff4.make_character_portrait_sprites(self.ROM_FF4jp)
|
||||
|
||||
@cached_property
|
||||
def battle_strips_ff6(self):
|
||||
return ff6.make_character_battle_sprites(self.ROM_FF6jp)
|
||||
|
||||
@cached_property
|
||||
def portraits_ff6(self):
|
||||
return ff6.make_character_portrait_sprites(self.ROM_FF6jp)
|
||||
|
||||
@cached_property
|
||||
def battle_bgs(self):
|
||||
return make_battle_backgrounds(ROM_SNES)
|
||||
|
||||
@cached_property
|
||||
def battle_strips(self):
|
||||
return make_character_battle_sprites(ROM_RPGe)
|
||||
|
||||
@cached_property
|
||||
def status_strips(self):
|
||||
return make_character_status_sprites(ROM_RPGe)
|
||||
|
||||
@cached_property
|
||||
def enemy_sprites(self):
|
||||
return make_enemy_sprites(ROM_RPGe)
|
||||
|
||||
@cached_property
|
||||
def enemy_sprite_data(self):
|
||||
return FFVStructs.EnemySprite.get_data(ROM_RPGe)
|
||||
|
||||
@cached_property
|
||||
def enemy_sprites_named(self):
|
||||
return [stack_labels(s, d[-2]) for s, d in zip(self.enemy_sprites, self.enemy_sprite_data)]
|
||||
|
||||
@cached_property
|
||||
def field_tiles(self):
|
||||
return make_all_field_tiles(ROM_SNES)
|
||||
|
||||
@cached_property
|
||||
def field_minitiles(self):
|
||||
return make_all_field_minitiles(ROM_SNES)
|
||||
|
||||
@cached_property
|
||||
def fieldmap_tiles(self):
|
||||
st_field_tiles = [stitch_tileset(ts) for ts in self.field_tiles]
|
||||
st_field_minitiles = [stitch_tileset(ts) for ts in self.field_minitiles]
|
||||
return [make_field_map_tile_pixmap(ROM_SNES, i, st_field_tiles, st_field_minitiles) for i in range(const.zone_count)]
|
||||
|
||||
@cached_property
|
||||
def glyph_sprites(self):
|
||||
return {
|
||||
'glyphs_en_s': generate_glyphs(ROM_RPGe, 0x11F000),
|
||||
'glyphs_en_l': generate_glyphs_large(ROM_RPGe, 0x03E800),
|
||||
'glyphs_jp_s': generate_glyphs(ROM_SNES, 0x11F000),
|
||||
'glyphs_jp_l': generate_glyphs_large(ROM_SNES, 0x03E800),
|
||||
'glyphs_kanji': generate_glyphs_large(ROM_SNES, 0x1BD000, 0x1AA), # Kanji are unchanged in EN version
|
||||
}
|
||||
perfcount()
|
||||
|
||||
imglist_headers = ['ID', 'EN Pointer', 'EN Address', 'EN String', 'EN Img', 'JP Pointer', 'JP Address', 'JP String', 'JP Img']
|
||||
@cached_property
|
||||
def worldmap_palettes(self):
|
||||
return [generate_palette(ROM_SNES, 0x0FFCC0+(i*0x100), length=0x160, transparent=True) for i in range(3)]
|
||||
|
||||
print('Generating String Images')
|
||||
string_images = {k: _make_string_img_list(*FFVStrings.blocks_SNES_RPGe[k], large=config.get('dialog'), **self.glyph_sprites) for k,config in FFVStrings.config.items()}
|
||||
ends_in_digit = re.compile('^([\w_]+)(\d+)')
|
||||
for k in sorted(list(string_images.keys())): # Pre-generate keys as we destructively iterate the dict
|
||||
if m := ends_in_digit.match(k):
|
||||
k0 = m[1]
|
||||
n = int(m[2])
|
||||
print(f'Collapsing strings list {k} into {k0}')
|
||||
string_images[k0] += string_images.pop(k)
|
||||
perfcount()
|
||||
@cached_property
|
||||
def worldmap_tiles(self):
|
||||
return make_worldmap_tiles_pixmap(ROM_SNES, 0x1B8000, 0x0FF9C0, 0x0FFCC0) + \
|
||||
make_worldmap_tiles_pixmap(ROM_SNES, 0x1BA000, 0x0FFAC0, 0x0FFDC0) + \
|
||||
make_worldmap_tiles_pixmap(ROM_SNES, 0x1BC000, 0x0FFBC0, 0x0FFEC0, length=128)
|
||||
|
||||
@cached_property
|
||||
def world_tiles(self):
|
||||
return [make_worldmap_blocks(ROM_SNES, 0x0FF0C0+(i*0x300), 0x1B8000+(i*0x2000), 0x0FF9C0+(i*0x100)) for i in range(3)]
|
||||
|
||||
tileset_headers = ("ID", "Offset", "Pointer", "Expected Length")
|
||||
tileset_data = []
|
||||
for i in range(0x1C):
|
||||
offset = 0x0F0000 + (i*2)
|
||||
pointer = 0x0F0000 + indirect(ROM_en, offset)
|
||||
length = indirect(ROM_en, offset+2) - indirect(ROM_en, offset)
|
||||
tileset_data.append((hex(i, 2), hex(offset, 6), hex(pointer, 6), hex(length, 4)))
|
||||
|
||||
npc_layers = []
|
||||
offset = 0x0E59C0
|
||||
for layer in range(const.npc_layer_count):
|
||||
i = offset + (layer*2)
|
||||
start = indirect(ROM_en, i) + offset
|
||||
next = indirect(ROM_en, i+2) + offset
|
||||
npcs = (next - start) // 7
|
||||
for npc in range(npcs):
|
||||
address = start + (npc*7)
|
||||
npc_layers.append([hex(i, 6), hex(layer, 3)] + parse_struct(ROM_en, address, const.npc_layer_structure))
|
||||
|
||||
|
||||
perfcount()
|
||||
print('Generating map tiles')
|
||||
worldmap_palettes = [generate_palette(ROM_jp, 0x0FFCC0+(i*0x100), length=0x160, transparent=True) for i in range(3)]
|
||||
world_tiles = [make_worldmap_blocks(ROM_jp, 0x0FF0C0+(i*0x300), 0x1B8000+(i*0x2000), 0x0FF9C0+(i*0x100)) for i in range(3)]
|
||||
#worldpixmaps = [make_worldmap_pixmap(ROM_jp, i, 0x0FFCC0+(t*0x100), world_tiles[t]) for i, t in enumerate([0, 1, 0, 2, 2])]
|
||||
world_blocks_pixmaps = []
|
||||
for i, tiles in enumerate(world_tiles):
|
||||
@cached_property
|
||||
def world_blocks_pixmaps(self):
|
||||
output = []
|
||||
for i, tiles in enumerate(self.world_tiles):
|
||||
a = []
|
||||
for t in tiles:
|
||||
t.setColorTable(worldmap_palettes[i])
|
||||
t.setColorTable(self.worldmap_palettes[i])
|
||||
a.append(QPixmap.fromImage(t))
|
||||
world_blocks_pixmaps.append(a)
|
||||
world_tile_stitches = [stitch_tileset_px(t) for t in world_blocks_pixmaps]
|
||||
worldpixmaps = [make_worldmap_pixmap2(ROM_jp, i, world_tile_stitches[t]) for i, t in enumerate([0, 1, 0, 2, 2])]
|
||||
perfcount()
|
||||
worldmap_tiles = make_worldmap_tiles_pixmap(ROM_jp, 0x1B8000, 0x0FF9C0, 0x0FFCC0)
|
||||
worldmap_tiles += make_worldmap_tiles_pixmap(ROM_jp, 0x1BA000, 0x0FFAC0, 0x0FFDC0)
|
||||
worldmap_tiles += make_worldmap_tiles_pixmap(ROM_jp, 0x1BC000, 0x0FFBC0, 0x0FFEC0, length=128)
|
||||
perfcount()
|
||||
output.append(a)
|
||||
return output
|
||||
|
||||
field_tiles = make_all_field_tiles(ROM_jp)
|
||||
field_minitiles = make_all_field_minitiles(ROM_jp)
|
||||
perfcount()
|
||||
st_field_tiles = [stitch_tileset(ts) for ts in field_tiles]
|
||||
st_field_minitiles = [stitch_tileset(ts) for ts in field_minitiles]
|
||||
perfcount()
|
||||
fieldmap_tiles = [make_field_map_tile_pixmap(ROM_jp, i, st_field_tiles, st_field_minitiles) for i in range(const.zone_count)]
|
||||
@cached_property
|
||||
def worldpixmaps(self):
|
||||
world_tile_stitches = [stitch_tileset_px(t) for t in self.world_blocks_pixmaps]
|
||||
return [make_worldmap_pixmap2(ROM_SNES, i, world_tile_stitches[t]) for i, t in enumerate([0, 1, 0, 2, 2])]
|
||||
#return [make_worldmap_pixmap(ROM_SNES, i, 0x0FFCC0+(t*0x100), self.world_tiles[t]) for i, t in enumerate([0, 1, 0, 2, 2])]
|
||||
|
||||
@cached_property
|
||||
def zone_pxs_and_field_blocks(self):
|
||||
perfcount()
|
||||
print('Generating field map blocks')
|
||||
zones = [parse_zone(ROM_jp, i) for i in range(const.zone_count)]
|
||||
field_blocksets = [get_field_map_block_layouts(ROM_jp, i) for i in range(28)]
|
||||
zones = [parse_zone(ROM_SNES, i) for i in range(const.zone_count)]
|
||||
field_blocksets = [get_field_map_block_layouts(ROM_SNES, i) for i in range(28)]
|
||||
perfcount()
|
||||
blockmaps = get_blockmaps(ROM_jp)
|
||||
|
||||
blockmaps = get_blockmaps(ROM_SNES)
|
||||
field_blocks = []
|
||||
zone_pxs = []
|
||||
block_cache = {'misses': 0, 'p_hits': 0, 'i_hits': 0}
|
||||
zone_px_cache = {'misses': 0, 'hits': 0}
|
||||
|
||||
fm_blocks = [make_field_map_blocks_px(ROM_jp, z, field_tiles, field_minitiles, field_blocksets, block_cache) for z in zones]
|
||||
#fm_blocks = [make_field_map_blocks_px2(ROM_jp, z, field_tiles, field_minitiles, field_blocksets, block_cache) for z in zones]
|
||||
fm_blocks = [make_field_map_blocks_px(ROM_SNES, z, self.field_tiles, self.field_minitiles, field_blocksets, block_cache) for z in zones]
|
||||
#fm_blocks = [make_field_map_blocks_px2(ROM_SNES, z, self.field_tiles, self.field_minitiles, field_blocksets, block_cache) for z in zones]
|
||||
print('Block cache results: {misses} misses, {p_hits} full hits, {i_hits} palette misses'.format(**block_cache))
|
||||
perfcount()
|
||||
for i, z in enumerate(zones):
|
||||
|
@ -156,81 +178,70 @@ class FF5Reader(QMainWindow):
|
|||
perfcount()
|
||||
del block_cache
|
||||
del zone_px_cache
|
||||
return zone_pxs, field_blocks
|
||||
|
||||
print('Generating Battle backgrounds')
|
||||
battle_bgs = make_battle_backgrounds(ROM_jp)
|
||||
@cached_property
|
||||
def zone_pxs(self):
|
||||
return self.zone_pxs_and_field_blocks[0]
|
||||
|
||||
@cached_property
|
||||
def field_blocks(self):
|
||||
return self.zone_pxs_and_field_blocks[1]
|
||||
|
||||
def __init__(self):
|
||||
QMainWindow.__init__(self, None)
|
||||
perfcount()
|
||||
print('Generating other sprites')
|
||||
self.battle_strips = make_character_battle_sprites(ROM_en)
|
||||
status_strips = make_character_status_sprites(ROM_en)
|
||||
enemy_sprites = make_enemy_sprites(ROM_en)
|
||||
enemy_sprite_data = FFVStructs.EnemySprite.get_data(ROM_en)
|
||||
enemy_sprites_named = [stack_labels(s, d[-2]) for s, d in zip(enemy_sprites, enemy_sprite_data)]
|
||||
print('Reading ROMs')
|
||||
self.ROM_FF4jp = load_raw(filename_jp_ff4)
|
||||
self.ROM_FF6jp = load_raw(filename_jp_ff6)
|
||||
print(len(self.ROM_FF4jp), filename_jp_ff4)
|
||||
print(len(self.ROM_FF6jp), filename_jp_ff6)
|
||||
perfcount()
|
||||
|
||||
print('Generating FF4 and FF6 stuff')
|
||||
self.battle_strips_ff4 = ff4.make_character_battle_sprites(ROM_FF4jp)
|
||||
self.field_strips_ff4 = ff4.make_character_field_sprites(ROM_FF4jp)
|
||||
self.portraits_ff4 = ff4.make_character_portrait_sprites(ROM_FF4jp)
|
||||
self.battle_strips_ff6 = ff6.make_character_battle_sprites(ROM_FF6jp)
|
||||
self.portraits_ff6 = ff6.make_character_portrait_sprites(ROM_FF6jp)
|
||||
print('Generating String Images')
|
||||
imglist_headers = ['ID', 'EN Pointer', 'EN Address', 'EN String', 'EN Img', 'JP Pointer', 'JP Address', 'JP String', 'JP Img']
|
||||
string_images = {k: _make_string_img_list(*FFVStrings.blocks_SNES_RPGe[k], large=config.get('dialog'), **self.glyph_sprites) for k,config in FFVStrings.config.items()}
|
||||
ends_in_digit = re.compile('^([\w_]+)(\d+)')
|
||||
for k in sorted(list(string_images.keys())): # Pre-generate keys as we destructively iterate the dict
|
||||
if m := ends_in_digit.match(k):
|
||||
k0 = m[1]
|
||||
n = int(m[2])
|
||||
print(f'Collapsing strings list {k} into {k0}')
|
||||
string_images[k0] += string_images.pop(k)
|
||||
perfcount()
|
||||
|
||||
print('Generating Tileset and NPC Layer offsets')
|
||||
tileset_headers = ("ID", "Offset", "Pointer", "Expected Length")
|
||||
tileset_data = []
|
||||
for i in range(0x1C):
|
||||
offset = 0x0F0000 + (i*2)
|
||||
pointer = 0x0F0000 + indirect(ROM_RPGe, offset)
|
||||
length = indirect(ROM_RPGe, offset+2) - indirect(ROM_RPGe, offset)
|
||||
tileset_data.append((hex(i, 2), hex(offset, 6), hex(pointer, 6), hex(length, 4)))
|
||||
npc_layers = []
|
||||
offset = 0x0E59C0
|
||||
for layer in range(const.npc_layer_count):
|
||||
i = offset + (layer*2)
|
||||
start = indirect(ROM_RPGe, i) + offset
|
||||
next = indirect(ROM_RPGe, i+2) + offset
|
||||
npcs = (next - start) // 7
|
||||
for npc in range(npcs):
|
||||
address = start + (npc*7)
|
||||
npc_layers.append([hex(i, 6), hex(layer, 3)] + parse_struct(ROM_RPGe, address, const.npc_layer_structure))
|
||||
perfcount()
|
||||
|
||||
print('Creating Qt Widgets')
|
||||
self.gamewidget = QTabWidget()
|
||||
self.ff4widget = QTabWidget()
|
||||
self.ff5widget = QTabWidget()
|
||||
self.ff6widget = QTabWidget()
|
||||
self.gamewidget.addTab(self.ff5widget, 'FFV')
|
||||
self.gamewidget.addTab(self.ff4widget, 'FFIV')
|
||||
self.gamewidget.addTab(self.ff6widget, 'FFVI')
|
||||
strings_tab = QTabWidget()
|
||||
structs_tab = QTabWidget()
|
||||
sprites_tab = QTabWidget()
|
||||
backgrounds_tab = QTabWidget()
|
||||
self.ff5widget.addTab(strings_tab, 'Strings')
|
||||
self.ff5widget.addTab(structs_tab, 'Structs')
|
||||
self.ff5widget.addTab(sprites_tab, 'Images')
|
||||
self.ff5widget.addTab(backgrounds_tab, 'Backgrounds')
|
||||
self.gamewidget.addTab(welcome := QLabel('Welcome to FF5Reader, click one of the game tabs at the top to get started.'), 'Welcome')
|
||||
self.gamewidget.addTab(ff5widget := QTabWidget(), 'FFV')
|
||||
self.gamewidget.addTab(ff4widget := QTabWidget(), 'FFIV')
|
||||
self.gamewidget.addTab(ff6widget := QTabWidget(), 'FFVI')
|
||||
|
||||
sprites_tab.addTab(make_px_table(self.glyph_sprites['glyphs_en_s'], scale=4), 'Glyphs (EN)')
|
||||
sprites_tab.addTab(make_px_table(self.glyph_sprites['glyphs_en_l'], scale=2), 'Glyphs (Dialogue EN)')
|
||||
sprites_tab.addTab(make_px_table(self.glyph_sprites['glyphs_jp_s'], scale=4), 'Glyphs (JP)')
|
||||
sprites_tab.addTab(make_px_table(self.glyph_sprites['glyphs_jp_l'], scale=2), 'Glyphs (Large JP)')
|
||||
sprites_tab.addTab(make_px_table(self.glyph_sprites['glyphs_kanji'], scale=2),'Glyphs (Kanji)')
|
||||
sprites_tab.addTab(make_px_table(self.battle_strips, cols=22, scale=2), 'Character Battle Sprites')
|
||||
sprites_tab.addTab(make_px_table(status_strips, cols=22, scale=2), 'Status Sprites')
|
||||
sprites_tab.addTab(make_px_table(enemy_sprites_named, cols=32, scale=1), 'Enemy Sprites')
|
||||
|
||||
backgrounds_tab.addTab(make_px_table(worldmap_tiles, cols=16, scale=4), 'Worldmap Tiles')
|
||||
backgrounds_tab.addTab(make_px_table(world_blocks_pixmaps[0], cols=16, scale=4), 'World 1 Blocks')
|
||||
backgrounds_tab.addTab(make_px_table(world_blocks_pixmaps[1], cols=16, scale=4), 'World 2 Blocks')
|
||||
backgrounds_tab.addTab(make_px_table(world_blocks_pixmaps[2], cols=16, scale=4), 'Underwater Blocks')
|
||||
backgrounds_tab.addTab(make_px_table(worldpixmaps, cols=1, scale=1, large=True), 'Worldmaps')
|
||||
backgrounds_tab.addTab(make_px_table(fieldmap_tiles, cols=16, scale=1), 'Fieldmap Tiles')
|
||||
backgrounds_tab.addTab(make_px_table(field_blocks, cols=16, scale=1), 'Field Blocks')
|
||||
backgrounds_tab.addTab(make_px_table(zone_pxs, cols=4, scale=1, large=1, basicrows=True), 'Zone')
|
||||
backgrounds_tab.addTab(make_px_table(battle_bgs, cols=8, scale=1), 'Battle BGs')
|
||||
|
||||
self.ff4widget.addTab(make_px_table(self.battle_strips_ff4, cols=16, scale=2), 'Character Battle Sprites')
|
||||
self.ff4widget.addTab(make_px_table(self.portraits_ff4, cols=14, scale=2), 'Character Portraits')
|
||||
self.ff4widget.addTab(make_px_table(self.field_strips_ff4, cols=17, scale=2), 'Character Field Sprites')
|
||||
self.ff6widget.addTab(make_px_table(self.battle_strips_ff6, cols=32, scale=2), 'Character Sprites')
|
||||
self.ff6widget.addTab(make_px_table(self.portraits_ff6, cols=19, scale=2), 'Character Portraits')
|
||||
|
||||
|
||||
structs_tab.addTab(make_table(FFVStructs.ZoneData.get_headers(), FFVStructs.ZoneData.get_data(ROM_en), True), 'Zones')
|
||||
structs_tab.addTab(make_table(FFVStructs.BattleBackground.get_headers(), FFVStructs.BattleBackground.get_data(ROM_jp), True), 'BattleBGs')
|
||||
structs_tab.addTab(make_table(FFVStructs.EnemySprite.get_headers(), enemy_sprite_data, True), 'Enemy Sprites')
|
||||
structs_tab.addTab(make_table(tileset_headers, tileset_data, True), 'Tilesets')
|
||||
structs_tab.addTab(make_table(const.npc_layer_headers, npc_layers, True), 'NPC Layers')
|
||||
|
||||
# Strings tabs
|
||||
for k, images in string_images.items():
|
||||
scale = 1 if FFVStrings.config[k].get('dialog') else 2
|
||||
caption = ' '.join(f'{w[0].upper()}{w[1:]}' for w in k.split('_'))
|
||||
strings_tab.addTab(make_table(imglist_headers, images, row_labels=False, scale=scale), caption)
|
||||
ff5widget.addTab(strings_tab := QTabWidget(), 'Strings')
|
||||
ff5widget.addTab(glyphs_tab := QTabWidget(), 'Glyphs')
|
||||
ff5widget.addTab(structs_tab := QTabWidget(), 'Structs')
|
||||
ff5widget.addTab(sprites_tab := QTabWidget(), 'Sprites')
|
||||
ff5widget.addTab(backgrounds_tab := QTabWidget(), 'Backgrounds')
|
||||
|
||||
self.string_decoder = QWidget()
|
||||
self.decoder_input = QLineEdit()
|
||||
|
@ -240,6 +251,76 @@ class FF5Reader(QMainWindow):
|
|||
self.string_decoder.setLayout(self.decoder_layout)
|
||||
strings_tab.addTab(self.string_decoder, 'String Decoder')
|
||||
|
||||
def load_tab_strings():
|
||||
for k, images in string_images.items():
|
||||
conf = FFVStrings.config[k]
|
||||
scale = 1 if conf.get('dialog') else 2
|
||||
caption = ' '.join(f'{w[0].upper()}{w[1:]}' for w in k.split('_'))
|
||||
strings_tab.addTab(tab := make_table(imglist_headers, images, row_labels=False, scale=scale), caption)
|
||||
tab.setColumnHidden(1, conf.get('rpge_ptr_offset') is None) # Hide EN Pointer if not indirect
|
||||
tab.setColumnHidden(5, conf.get('snes_ptr_offset') is None) # Hide JP Pointer if not indirect
|
||||
tab.resizeColumnsToContents()
|
||||
for i in range(len(imglist_headers)):
|
||||
if tab.columnWidth(i) > 360:
|
||||
tab.setColumnWidth(i, 360)
|
||||
|
||||
def load_tab_glyphs():
|
||||
glyphs_tab.addTab(make_px_table(self.glyph_sprites['glyphs_en_s'], scale=3), 'Small EN')
|
||||
glyphs_tab.addTab(make_px_table(self.glyph_sprites['glyphs_en_l'], scale=2), 'Dialogue EN')
|
||||
glyphs_tab.addTab(make_px_table(self.glyph_sprites['glyphs_jp_s'], scale=3), 'Small JP')
|
||||
glyphs_tab.addTab(make_px_table(self.glyph_sprites['glyphs_jp_l'], scale=2), 'Dialogue JP')
|
||||
glyphs_tab.addTab(make_px_table(self.glyph_sprites['glyphs_kanji'], scale=2),'Kanji')
|
||||
|
||||
def load_tab_structs():
|
||||
structs_tab.addTab(make_table(FFVStructs.ZoneData.get_headers(), FFVStructs.ZoneData.get_data(ROM_RPGe), True), 'Zones')
|
||||
structs_tab.addTab(make_table(FFVStructs.BattleBackground.get_headers(), FFVStructs.BattleBackground.get_data(ROM_SNES), True), 'BattleBGs')
|
||||
structs_tab.addTab(make_table(FFVStructs.EnemySprite.get_headers(), self.enemy_sprite_data, True), 'Enemy Sprites')
|
||||
structs_tab.addTab(make_table(tileset_headers, tileset_data, True), 'Tilesets')
|
||||
structs_tab.addTab(make_table(const.npc_layer_headers, npc_layers, True), 'NPC Layers')
|
||||
|
||||
def load_tab_sprites():
|
||||
sprites_tab.addTab(make_px_table(self.battle_strips, cols=22, scale=2), 'Character Battle Sprites')
|
||||
sprites_tab.addTab(make_px_table(self.status_strips, cols=22, scale=2), 'Status Sprites')
|
||||
sprites_tab.addTab(make_px_table(self.enemy_sprites_named, cols=32, scale=1), 'Enemy Sprites')
|
||||
|
||||
def load_tab_backgrounds():
|
||||
backgrounds_tab.addTab(make_px_table(self.worldmap_tiles, cols=16, scale=4), 'Worldmap Tiles')
|
||||
backgrounds_tab.addTab(make_px_table(self.world_blocks_pixmaps[0], cols=16, scale=3), 'World 1 Blocks')
|
||||
backgrounds_tab.addTab(make_px_table(self.world_blocks_pixmaps[1], cols=16, scale=3), 'World 2 Blocks')
|
||||
backgrounds_tab.addTab(make_px_table(self.world_blocks_pixmaps[2], cols=16, scale=3), 'Underwater Blocks')
|
||||
backgrounds_tab.addTab(make_px_table(self.worldpixmaps, cols=1, scale=1, large=True), 'Worldmaps')
|
||||
backgrounds_tab.addTab(make_px_table(self.fieldmap_tiles, cols=16, scale=1), 'Fieldmap Tiles')
|
||||
backgrounds_tab.addTab(make_px_table(self.field_blocks, cols=16, scale=1), 'Field Blocks')
|
||||
backgrounds_tab.addTab(make_px_table(self.zone_pxs, cols=4, scale=1, large=1, basicrows=True), 'Zone')
|
||||
backgrounds_tab.addTab(make_px_table(self.battle_bgs, cols=8, scale=1), 'Battle BGs')
|
||||
|
||||
tab_loaders = [load_tab_strings, load_tab_glyphs, load_tab_structs, load_tab_sprites, load_tab_backgrounds]
|
||||
def load_tab(index: int):
|
||||
if fn := tab_loaders[index]:
|
||||
fn()
|
||||
tab_loaders[index] = None
|
||||
ff5widget.currentChanged.connect(load_tab)
|
||||
|
||||
def load_ff5():
|
||||
load_tab(ff5widget.currentIndex())
|
||||
pass
|
||||
|
||||
def load_ff4():
|
||||
ff4widget.addTab(make_px_table(self.battle_strips_ff4, cols=16, scale=2), 'Character Battle Sprites')
|
||||
ff4widget.addTab(make_px_table(self.portraits_ff4, cols=14, scale=2), 'Character Portraits')
|
||||
ff4widget.addTab(make_px_table(self.field_strips_ff4, cols=17, scale=2), 'Character Field Sprites')
|
||||
|
||||
def load_ff6():
|
||||
ff6widget.addTab(make_px_table(self.battle_strips_ff6, cols=32, scale=2), 'Character Sprites')
|
||||
ff6widget.addTab(make_px_table(self.portraits_ff6, cols=19, scale=2), 'Character Portraits')
|
||||
|
||||
game_tab_loaders = [None, load_ff5, load_ff4, load_ff6]
|
||||
def load_game_tab(index: int):
|
||||
if fn := game_tab_loaders[index]:
|
||||
fn()
|
||||
game_tab_loaders[index] = None
|
||||
self.gamewidget.currentChanged.connect(load_game_tab)
|
||||
|
||||
layout = QHBoxLayout()
|
||||
layout.addWidget(self.gamewidget)
|
||||
self.main_widget = QWidget(self)
|
||||
|
|
Loading…
Reference in New Issue