# How SKCombat placed each atrezzo / platform mesh in its square: the Unity prefabs' mesh objects and their
# local offsets from the prefab root (the cell's anchor), plus the tile's size and Atrezzo flags.
# Writes placement.json: {fbx file name: {"prefab", "offset": [x, y, z] (tiles), "size": [w, h], "ignoreP": bool}}.
# Run: python -I placement.py <Unity project dir> <out dir>
import os, re, sys, json
root, out_dir = sys.argv[1], sys.argv[2]
guid = {}
for d, _, fs in os.walk(os.path.join(root, 'Assets')):
    for f in fs:
        if f.endswith('.meta'):
            t = open(os.path.join(d, f), encoding='utf-8', errors='ignore').read(3000)
            m = re.search(r'guid: ([0-9a-f]{32})', t)
            if m: guid[m.group(1)] = os.path.join(d, f[:-5])
def docs(path):
    out = {}
    for part in re.split(r'^--- ', open(path, encoding='utf-8', errors='ignore').read(), flags=re.M)[1:]:
        h = re.match(r'!u!(\d+) &(\d+)', part)
        if h: out[h.group(2)] = (h.group(1), part)
    return out
vec = lambda s, k: [float(v) for v in re.search(k + r': \{x: ([-\d.e]+), y: ([-\d.e]+), z: ([-\d.e]+)', s).groups()]
res = {}
odd = []
for folder in ('Tiles(Atrezzos)', 'Tiles(Platforms)'):
    for d, _, fs in os.walk(os.path.join(root, 'Assets', 'References', folder)):
        for f in fs:
            if not f.endswith('.prefab') or 'OLD' in d: continue
            path = os.path.join(d, f)
            D = docs(path)
            tf = {}  # GameObject id → Transform text
            for fid, (typ, body) in D.items():
                if typ == '4':
                    go = re.search(r'm_GameObject: \{fileID: (\d+)\}', body).group(1)
                    tf[go] = (fid, body)
            byfid = {fid: body for fid, (typ, body) in D.items() if typ == '4'}
            def offset(fid):
                """position of a Transform relative to the prefab root (rotations ignored: these prefabs don't turn their meshes)"""
                p = [0.0, 0.0, 0.0]
                while fid and fid != '0' and fid in byfid:
                    body = byfid[fid]
                    father = re.search(r'm_Father: \{fileID: (\d+)\}', body).group(1)
                    if father == '0': break  # the root itself = the cell anchor
                    lp = vec(body, 'm_LocalPosition')
                    p = [p[i] + lp[i] for i in range(3)]
                    fid = father
                return p
            size = re.search(r'mySize: \{x: ([\d.]+), y: ([\d.]+)\}', open(path, encoding='utf-8', errors='ignore').read())
            ign = re.search(r'ignorePOffset: (\d)', open(path, encoding='utf-8', errors='ignore').read())
            for fid, (typ, body) in D.items():
                if typ != '33': continue
                mm = re.search(r'm_Mesh: \{fileID: (\d+), guid: ([0-9a-f]{32})', body)
                if not mm or mm.group(2) not in guid: continue
                fbx = os.path.basename(guid[mm.group(2)])
                if not fbx.lower().endswith('.fbx'): continue
                go = re.search(r'm_GameObject: \{fileID: (\d+)\}', body).group(1)
                name = re.search(r'm_Name: (.*)', D[go][1]).group(1).strip() if go in D else ''
                if 'Fow' in name: continue  # fog-of-war twin
                off = [round(v / 1.5, 3) for v in offset(tf[go][0])] if go in tf else [0, 0, 0]
                if fbx not in res or res[fbx]['offset'] == [0, 0, 0] and off != [0, 0, 0] and False:
                    res[fbx] = {'prefab': f, 'offset': off, 'size': [float(size.group(1)), float(size.group(2))] if size else [1, 1], 'ignoreP': bool(ign and ign.group(1) == '1')}
                if any(abs(v) > 0.001 for v in off): odd.append((f, name, fbx, off))
json.dump(res, open(os.path.join(out_dir, 'placement.json'), 'w'), indent=1)
print(len(res), 'meshes;', len(odd), 'with an offset from the cell anchor:')
for o in odd: print('  ', o)
big = [(k, v['size']) for k, v in res.items() if v['size'] != [1, 1]]
print(len(big), 'bigger than one square:', big[:20])
print('ignoreP:', [k for k, v in res.items() if v['ignoreP']][:20])
