v0.6.0 update

Adds atlas, thingy output formats
Adds configurable filenames
Adds an option to force 16-bit tilemap indexes
Adds an option to start at a nonzero tilemap index
current
Nathan Deren 2018-06-06 13:14:02 -07:00
parent 3584999c55
commit c75e865ccf
1 changed files with 81 additions and 21 deletions

View File

@ -1,13 +1,14 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import json import json
from math import ceil from math import ceil, floor
from PyQt5.QtGui import QGuiApplication, QPixmap, QImage, QColor, QPainter from PyQt5.QtGui import QGuiApplication, QPixmap, QImage, QColor, QPainter
class Font: class Font:
"""A simple class for managing Smeargle's font data.""" """A simple class for managing Smeargle's font data."""
def __init__(self, filename): def __init__(self, filename):
"""Creates the font object. """Creates the font object.
@ -75,10 +76,15 @@ class Font:
class Script: class Script:
def __init__(self, filename, max_tiles=0, atlas=False, tile_offset=0): def __init__(self, filename, raw_fn=None, deduped_fn=None, tilemap_fn=None,
max_tiles=0, output_format=None, tile_offset=0, leading_zeroes=False):
self.max_tiles = max_tiles self.max_tiles = max_tiles
self.atlas = atlas self.output_format = output_format
self.tile_offset = tile_offset self.tile_offset = tile_offset
self.leading_zeroes = leading_zeroes
self.raw_fn = raw_fn
self.deduped_fn = deduped_fn
self.tilemap_fn = tilemap_fn
with open(filename, mode='r', encoding='UTF-8') as f: with open(filename, mode='r', encoding='UTF-8') as f:
self._text = f.read().split('\n') self._text = f.read().split('\n')
@ -119,8 +125,7 @@ class Script:
return lines return lines
@staticmethod def generate_tilemap(self, font, lines):
def generate_tilemap(font, lines):
tilemap = {} tilemap = {}
raw_tiles = [] raw_tiles = []
compressed_tiles = [] compressed_tiles = []
@ -154,7 +159,27 @@ class Script:
if data not in tilemap.keys(): if data not in tilemap.keys():
tilemap[data] = tile tilemap[data] = tile
compressed_tiles.append(tile) compressed_tiles.append(tile)
map_idx[data] = '0x{:02x}'.format(unique) if self.output_format == 'atlas':
index = unique + self.tile_offset
upper_val = int(floor(index / 256))
lower_val = int(index % 256)
if upper_val > 0 or self.leading_zeroes is True:
map_idx[data] = "<${:02x}><${:02x}>".format(upper_val, lower_val)
else:
map_idx[data] = "<${:02x}>".format(lower_val)
elif self.output_format == 'thingy':
index = unique + self.tile_offset
upper_val = int(floor(index / 256))
lower_val = int(index % 256)
if upper_val > 0 or self.leading_zeroes is True:
map_idx[data] = "{:02x}{:02x}".format(upper_val, lower_val)
else:
map_idx[data] = "{:02x}".format(lower_val)
else:
if self.leading_zeroes:
map_idx[data] = '0x{:04x}'.format(unique + self.tile_offset)
else:
map_idx[data] = '0x{:02x}'.format(unique + self.tile_offset)
unique += 1 unique += 1
raw_tiles.append(tile) raw_tiles.append(tile)
@ -163,7 +188,10 @@ class Script:
column += font.width column += font.width
count -= 1 count -= 1
if self.output_format is None:
indexes.append((text, ' '.join(tile_idx))) indexes.append((text, ' '.join(tile_idx)))
else:
indexes.append((text, ''.join(tile_idx)))
return compressed_tiles, raw_tiles, map_idx, indexes, total, unique return compressed_tiles, raw_tiles, map_idx, indexes, total, unique
def render_tiles(self, font, tiles): def render_tiles(self, font, tiles):
@ -203,18 +231,36 @@ class Game:
for name, file in self._data['fonts'].items(): for name, file in self._data['fonts'].items():
self._fonts[name] = Font(file) self._fonts[name] = Font(file)
valid_formats = ['thingy', 'atlas', None]
defaults = {
'max_tiles_per_line': 0,
'output_format': None,
'tile_offset': 0,
'leading_zeroes': False,
'raw_fn': None,
'deduped_fn': None,
'tilemap_fn': None
}
for script, data in self._data['scripts'].items(): for script, data in self._data['scripts'].items():
if 'max_tiles_per_line' not in data:
data['max_tiles_per_line'] = 0 # Add defaults to script data if not present
if 'atlas' not in data: for k, v in defaults.items():
data['atlas'] = False if k not in data:
if 'tile_offset' not in data: data[k] = v
data['tile_offset'] = 0
if data['output_format'] not in valid_formats:
raise ValueError("output_format must be one of {} or omitted entirely".format(valid_formats[:-1]))
self._scripts[script] = ( self._scripts[script] = (
Script(filename=script, Script(filename=script,
raw_fn=data['raw_fn'],
deduped_fn=data['deduped_fn'],
tilemap_fn=data['tilemap_fn'],
max_tiles=data['max_tiles_per_line'], max_tiles=data['max_tiles_per_line'],
atlas=data['atlas'], output_format=data['output_format'],
tile_offset=data['tile_offset']), tile_offset=data['tile_offset'],
leading_zeroes=data['leading_zeroes']),
self._fonts[data['font']] self._fonts[data['font']]
) )
@ -233,12 +279,23 @@ class Game:
filebase = os.path.split(script)[-1] filebase = os.path.split(script)[-1]
name, ext = os.path.splitext(filebase) name, ext = os.path.splitext(filebase)
output_raw = os.path.join(render_path, name + '_raw.png')
output_comp = os.path.join(render_path, name + '_compressed.png')
output_map = os.path.join(render_path, name + '_index.txt')
script, font = self._scripts[script] script, font = self._scripts[script]
if script.raw_fn is None:
output_raw = os.path.join(render_path, name + '_raw.png')
else:
output_raw = os.path.join(render_path, script.raw_fn)
if script.deduped_fn is None:
output_comp = os.path.join(render_path, name + '_compressed.png')
else:
output_comp = os.path.join(render_path, script.deduped_fn)
if script.tilemap_fn is None:
output_map = os.path.join(render_path, name + '_index.txt')
else:
output_map = os.path.join(render_path, script.tilemap_fn)
if output: print('Rendering text...') if output: print('Rendering text...')
lines = script.render_lines(font) lines = script.render_lines(font)
if output: print('Text rendered.') if output: print('Text rendered.')
@ -258,6 +315,9 @@ class Game:
if output: print('Writing map index...', end='') if output: print('Writing map index...', end='')
with open(output_map, mode='wt') as f: with open(output_map, mode='wt') as f:
for text, index in indexes: for text, index in indexes:
if script.output_format == 'thingy':
f.write('{}={}\n'.format(index, text))
else:
f.write('{} = {}\n'.format(text, index)) f.write('{} = {}\n'.format(text, index))
if output: print('done.') if output: print('done.')