main
ae007 Project page: AFS_Adom rev A (Rice Eclipse AFS clean-room AI redesign): highlight reel and narrated process video with… cbe460e 7d ago
"""Offline fallback for the reference/value field moves: KiCad 10.0.6's IPC refuses PCB_FIELD updates through
kicad_silk_fields_batch (ISC_INVALID_TYPE: PCB_FIELD_T unhandled). Edits the saved board file: for every update in
apply_fields.json (field UUID -> board x/y, layer, height, stroke) rewrite that property's (at ...), (layer ...),
(effects (font (size) (thickness))) and drop (hide yes). Positions go into the footprint's local frame (inverse of the
pcb.py rotation convention); the text angle is written relative to the footprint. The board is reloaded in KiCad with
File > Revert afterwards and re-validated natively."""
import json, re, math, sys
S = '/tmp/claude-1001/-home-adom-project/8819fb5f-c2c6-4524-9528-99428cd6b88e/scratchpad'
src, dst = sys.argv[1], sys.argv[2]
upd = {u['id']: u for u in json.load(open(S + '/AFS_Adom/aiflow/silk/apply_fields.json'))['update']}
board = json.load(open(S + '/AFS_Adom/aiflow/silk/board.json'))
fp_of = {}
for fp in board['footprints']:
    for name, pr in fp['props'].items(): fp_of[pr['uuid']] = (fp, name)
txt = open(src, encoding='utf-8').read()
done = 0; missing = []
for uuid, u in upd.items():
    if uuid not in fp_of: missing.append(uuid); continue
    fp, name = fp_of[uuid]
    i = txt.find('(uuid "%s")' % uuid)
    if i < 0: missing.append(uuid); continue
    start = txt.rfind('(property "%s"' % name, 0, i)
    # end of this property block: match parens from start
    d = 0; k = start
    while True:
        c = txt[k]
        if c == '(': d += 1
        elif c == ')':
            d -= 1
            if d == 0: break
        k += 1
    block = txt[start:k + 1]
    r = math.radians(fp['rot']); bx, by = u['x'] - fp['x'], u['y'] - fp['y']
    px = bx * math.cos(r) - by * math.sin(r); py = bx * math.sin(r) + by * math.cos(r)
    ang = (u.get('rotation', 0) - fp['rot']) % 360
    nb = re.sub(r'\(at [-\d.]+ [-\d.]+( [-\d.]+)?\)', '(at %.3f %.3f %g)' % (px, py, ang), block, count=1)
    nb = re.sub(r'\(layer "[^"]+"\)', '(layer "%s")' % u['layer'], nb, count=1)
    nb = re.sub(r'\(size [-\d.]+ [-\d.]+\)', '(size %g %g)' % (u['height'], u['width']), nb, count=1)
    if '(thickness' in nb: nb = re.sub(r'\(thickness [-\d.]+\)', '(thickness %g)' % u['stroke'], nb, count=1)
    else: nb = nb.replace('(size %g %g)' % (u['height'], u['width']), '(size %g %g)\n\t\t\t\t(thickness %g)' % (u['height'], u['width'], u['stroke']), 1)
    nb = re.sub(r'\n\s*\(hide yes\)', '', nb)
    txt = txt[:start] + nb + txt[k + 1:]; done += 1
open(dst, 'w', encoding='utf-8').write(txt)
print('fields rewritten', done, 'missing', len(missing))