Add the REM interface generators (tools) and ignore dumps, logs and server files
make_icon_3db, make_image_3db and make_hud_txm with their helpers, standalone (the name CRC table is in flcrc.py). The .gitignore keeps crash dumps, logs, traces, debug symbols and everything of the server out of the mod.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
"""A coloured Freelancer interface image (.3db) from a PNG -- for pictures in the REM windows
|
||||
(statistics medals, banners, portraits), shown with a StaticControl like the inventory's item
|
||||
icons. Unlike make_icon_3db.py the colours stay and the quad keeps the picture's aspect.
|
||||
|
||||
python tools/make_image_3db.py <in.png> <out.3db> <name> [--size 256] [--nocrop] [--crop x0,y0,x1,y1]
|
||||
|
||||
The transparent border is cut off (unless --nocrop), the picture is stretched into a square
|
||||
texture of --size pixels (three mips) and drawn on a quad of the picture's aspect, the longer
|
||||
side as long as the retail icon quad. --crop cuts that pixel rectangle out first (a banner
|
||||
strip from a square picture). <name> gives the material "UI_REMIMG_<name>", the texture
|
||||
"REMIMG_<name>.tga" and the mesh library "rem_img_<name>.lod0.vms".
|
||||
"""
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
import flcrc # noqa: E402
|
||||
import make_icon_3db as icon # noqa: E402
|
||||
import utf # noqa: E402
|
||||
|
||||
HALF = icon.QUAD_HALF
|
||||
Z = icon.QUAD_Z
|
||||
INDICES = [0, 1, 2, 1, 3, 2]
|
||||
|
||||
|
||||
def crop(w, h, rows):
|
||||
xs = [x for line in rows for x, p in enumerate(line) if p[3] > 8]
|
||||
ys = [y for y, line in enumerate(rows) if any(p[3] > 8 for p in line)]
|
||||
if not xs:
|
||||
return w, h, rows
|
||||
x0, x1, y0, y1 = min(xs), max(xs) + 1, min(ys), max(ys) + 1
|
||||
return x1 - x0, y1 - y0, [line[x0:x1] for line in rows[y0:y1]]
|
||||
|
||||
|
||||
def make(png, out, name, size=256, do_crop=True, rect=None):
|
||||
w, h, rows = icon.read_png(png)
|
||||
if rect is not None:
|
||||
x0, y0, x1, y1 = rect
|
||||
w, h, rows = x1 - x0, y1 - y0, [line[x0:x1] for line in rows[y0:y1]]
|
||||
if do_crop:
|
||||
w, h, rows = crop(w, h, rows)
|
||||
hx, hy = (HALF, HALF * h / w) if w >= h else (HALF * w / h, HALF)
|
||||
quad = [(-hx, hy, Z, 0.0, 1.0), (-hx, -hy, Z, 0.0, 0.0), (hx, hy, Z, 1.0, 1.0), (hx, -hy, Z, 1.0, 0.0)]
|
||||
mips = []
|
||||
s = size
|
||||
for _ in range(3):
|
||||
mips.append(icon.tga(icon.resample(w, h, rows, s)))
|
||||
s = max(4, s // 2)
|
||||
material = 'UI_REMIMG_' + name
|
||||
texture = 'REMIMG_' + name + '.tga'
|
||||
library = 'rem_img_' + name.lower() + '.lod0.vms'
|
||||
data = struct.pack('<IIHHHH', 1, 4, 1, len(INDICES), 0x102, len(quad))
|
||||
data += struct.pack('<IHHHH', flcrc.crc(material), 0, len(quad) - 1, len(INDICES), 204)
|
||||
data += struct.pack('<%dH' % len(INDICES), *INDICES)
|
||||
for v in quad:
|
||||
data += struct.pack('<5f', *v)
|
||||
ref = struct.pack('<IIHHHHHH10f', 60, flcrc.crc(library), 0, len(quad), 0, len(INDICES), 0, 1,
|
||||
hx, -hx, hy, -hy, Z, Z, 0.0, 0.0, Z, max(hx, hy) * 1.5094)
|
||||
N = utf.Node
|
||||
root = N('\\', children=[
|
||||
N('Exporter Version', data=b'REM make_image_3db\0'),
|
||||
N('VMeshLibrary', children=[N(library, children=[N('VMeshData', data=data)])]),
|
||||
N('VMeshPart', children=[N('VMeshRef', data=ref)]),
|
||||
N('Material library', children=[
|
||||
N('Material count', data=struct.pack('<I', 1)),
|
||||
N(material, children=[N('Type', data=b'DcDtOcOt\0'), N('Dt_name', data=texture.encode() + b'\0'),
|
||||
N('Dt_flags', data=struct.pack('<I', 64))])]),
|
||||
N('Texture library', children=[
|
||||
N(texture, children=[N('MIP%d' % i, data=m) for i, m in enumerate(mips)])]),
|
||||
])
|
||||
os.makedirs(os.path.dirname(os.path.abspath(out)), exist_ok=True)
|
||||
utf.write(out, root)
|
||||
return w, h
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
argv = sys.argv[1:]
|
||||
size = 256
|
||||
if '--size' in argv:
|
||||
i = argv.index('--size')
|
||||
size = int(argv[i + 1])
|
||||
del argv[i:i + 2]
|
||||
rect = None
|
||||
if '--crop' in argv:
|
||||
i = argv.index('--crop')
|
||||
rect = tuple(int(v) for v in argv[i + 1].split(','))
|
||||
del argv[i:i + 2]
|
||||
args = [a for a in argv if not a.startswith('--')]
|
||||
if len(args) != 3:
|
||||
print(__doc__)
|
||||
sys.exit(1)
|
||||
w, h = make(args[0], args[1], args[2], size, '--nocrop' not in argv, rect)
|
||||
print('wrote', args[1], '(%dx%d)' % (w, h))
|
||||
Reference in New Issue
Block a user