app
Fusion - the Fusion 360 Bridge
Public Made by Adomby adom
Drive Autodesk Fusion 360 from the cloud via Adom Bridge: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling.
master
John Lauer
Add bounded obstacle planning and live calculations using the Adom activity palette
e936bc3
1mo ago
"""Compose synchronized native Fusion and Adom-palette captures; preserve actual live text."""
from pathlib import Path
import json,subprocess,sys
ROOT=Path(__file__).resolve().parent
sys.path.insert(0,str(ROOT.parent/'crossbar'))
from render_crossbar import HEADER,stamp
TAKE=ROOT/'take-04'
board=next(TAKE.glob('window-8916576-*.mp4'));panel=next(TAKE.glob('window-11280636-*.mp4'))
final=json.loads((TAKE/'final.json').read_text());assert final['drc']['clean'] and not final['remainingNets']
calls=json.loads((TAKE/'calls.json').read_text());starts=[c for c in calls if c['verb']=='desktop_record_window_start']
offset=starts[1]['start']-starts[0]['start']
def probe(f):return json.loads(subprocess.check_output(['ffprobe','-v','error','-show_streams','-of','json',str(f)]))['streams'][0]
b,p=probe(board),probe(panel)
assert b['r_frame_rate']==p['r_frame_rate']=='30/1'
# Trim the long completed-state tail; final hold in output is five seconds.
common=min(float(b['duration'])-offset,float(p['duration']))
end=common-3
for speed in [3,1]:
name=f'fusion-obstacle-live-{speed}x';duration=end/speed+5
events=[]
def text(a,z,t):events.append(f'Dialogue: 0,{stamp(a)},{stamp(z)},Main,,0,0,0,,{t}')
text(0,duration,r'{\an7\pos(36,18)\fs36\b1\c&H00E5CF65&}CODEX ASTRA IN ADOM HYDROGEN / LIVE FUSION ROUTING')
text(0,duration,fr'{{\an7\pos(1455,75)\fs25}}{speed}x playback / live SSE panel')
text(0,duration,r'{\an7\pos(36,75)\fs25}Native AB capture / board + live Adom palette')
text(0,end/speed,r'{\an2\pos(960,1034)\fs28}fusion_plan_route calculates paths; fusion_route_net creates and verifies copper.\NThe Adom palette displays actual results during routing. No external router.')
text(end/speed,duration,r'{\an2\pos(960,1034)\fs30}3 connections / 8 new segments / 2 vias / both barriers preserved.\Nfusion_routing_drc: 0 errors / 0 warnings / 0 airwires.')
ass=ROOT/(name+'.ass');ass.write_text(HEADER+'\n'.join(events)+'\n')
# Board crop retains editor toolbar + all board copper. Panel crop removes unused lower area.
vf=(f'[0:v]trim=start={offset}:end={offset+end},setpts=(PTS-STARTPTS)/{speed},fps=30,crop=1700:1440:0:0,scale=1062:900,pad=1370:900:154:0:color=0x0a0f13[b];'
f'[1:v]trim=start=0:end={end},setpts=(PTS-STARTPTS)/{speed},fps=30,crop=570:850:0:0,scale=570:850,pad=570:900:0:0:color=0x0a0f13[p];'
f'[b][p]hstack=inputs=2,crop=1920:900:0:0,pad=1920:1080:0:110:color=0x0a0f13,tpad=stop_mode=clone:stop_duration=5,ass={ass}[v]')
out=ROOT/(name+'.mp4')
subprocess.run(['ffmpeg','-v','warning','-i',str(board),'-i',str(panel),'-filter_complex',vf,'-map','[v]','-an','-c:v','libx264','-preset','fast','-crf','19','-pix_fmt','yuv420p','-movflags','+faststart','-y',str(out)],check=True)
(ROOT/(name+'.edit.json')).write_text(json.dumps({'sources':[str(board),str(panel)],'boardOffsetSeconds':offset,'synchronization':'Call-start timestamps; first-frame timing can differ by capture initialization latency','commonSourceSeconds':[0,end],'trimmedCompletedTailSeconds':common-end,'speed':speed,'finalHoldSeconds':5,'durationSeconds':duration,'livePanel':'Original native Adom palette video; no reconstructed status text'},indent=2)+'\n')
print(out,flush=True)