# 팩 데모 프리팹을 레퍼런스로 화면을 옮길 때 수치 추출(PD 2026-11-09 화면별 레퍼런스 재제작) — 예: -I Tools/prefab_tree.py "<팩>/Prefabs/Prefabs_DemoScene_Panels/Collection_List.prefab" "<팩>/ResourcesData" Content 4 # Unity 프리팹 YAML → 계층(이름 · 앵커 · 위치 · 크기 · 이미지 스프라이트/색 · TMP 글자/크기/색) 출력 — 인수: 프리팹 · 스프라이트 루트 · [시작 이름] · [최대 깊이] import os import re import sys path, sproot = sys.argv[1], sys.argv[2] start = sys.argv[3] if len(sys.argv) > 3 else None maxd = int(sys.argv[4]) if len(sys.argv) > 4 else 99 txt = open(path, encoding='utf-8', errors='ignore').read() docs = {} for m in re.finditer(r'--- !u!(\d+) &(-?\d+)[^\n]*\n(.*?)(?=\n--- !u!|\Z)', txt, re.S): docs[m.group(2)] = (m.group(1), m.group(3)) guid2name = {} for root, _, files in os.walk(sproot): for f in files: if f.endswith('.meta'): g = re.search(r'guid: (\w+)', open(os.path.join(root, f), encoding='utf-8', errors='ignore').read()) if g: guid2name[g.group(1)] = f[:-5] def field(body, key): m = re.search(r'\n\s*' + key + r': (.*)', '\n' + body) return m.group(1).strip() if m else '' go_comps = {} go_name = {} for fid, (t, body) in docs.items(): if t == '1': go_name[fid] = field(body, 'm_Name') go_comps[fid] = re.findall(r'component: \{fileID: (-?\d+)\}', body) rt_of = {} for g, comps in go_comps.items(): for c in comps: if c in docs and docs[c][0] == '224': rt_of[g] = c go_of_rt = {v: k for k, v in rt_of.items()} def v2(s): m = re.findall(r'[-\d.]+', s) return '(' + ','.join(str(round(float(x), 1)) for x in m) + ')' if m else '' def desc(g): rt = docs[rt_of[g]][1] out = '%s a%s-%s p%s pos%s size%s' % (go_name[g], v2(field(rt, 'm_AnchorMin')), v2(field(rt, 'm_AnchorMax')), v2(field(rt, 'm_Pivot')), v2(field(rt, 'm_AnchoredPosition')), v2(field(rt, 'm_SizeDelta'))) for c in go_comps[g]: if c not in docs or docs[c][0] != '114': continue b = docs[c][1] if not re.search(r'm_Enabled: 1', b): continue sp = re.search(r'm_Sprite: \{fileID: -?\d+, guid: (\w+)', b) col = re.search(r'm_Color: \{r: ([\d.]+), g: ([\d.]+), b: ([\d.]+), a: ([\d.]+)\}', b) if sp: hexc = '#%02X%02X%02X/%.2f' % tuple([int(float(x) * 255 + 0.5) for x in col.groups()[:3]] + [float(col.group(4))]) if col else '' ty = field(b, 'm_Type') ppu = field(b, 'm_PixelsPerUnitMultiplier') out += ' | IMG ' + guid2name.get(sp.group(1), sp.group(1)[:8]) + ' ' + hexc + ' t' + ty + (' ppu' + ppu if ppu and ppu != '1' else '') tx = re.search(r'm_text: (.*)', b) if tx: fc = re.search(r'm_fontColor: \{r: ([\d.]+), g: ([\d.]+), b: ([\d.]+), a: ([\d.]+)\}', b) hexc = '#%02X%02X%02X' % tuple(int(float(x) * 255 + 0.5) for x in fc.groups()[:3]) if fc else '' out += ' | TXT "%s" size%s %s align%s' % (tx.group(1)[:30], field(b, 'm_fontSize'), hexc, field(b, 'm_HorizontalAlignment') or field(b, 'm_textAlignment')) if 'm_EffectDistance' in b: out += ' | FX ' + v2(field(b, 'm_EffectDistance')) return out def walk(g, d): if d > maxd: return print(' ' * d + desc(g)) rt = docs[rt_of[g]][1] for c in re.findall(r'- \{fileID: (-?\d+)\}', rt.split('m_Children:')[1].split('m_Father')[0]) if 'm_Children:' in rt else []: if c in go_of_rt: walk(go_of_rt[c], d + 1) roots = [g for g in go_name if g in rt_of and (start and go_name[g] == start)] if not roots: roots = [g for g in go_name if g in rt_of and field(docs[rt_of[g]][1], 'm_Father') == '{fileID: 0}'] walk(roots[0], 0)