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.
← Commit history
#135: no_3d_package preflight; seed reverted
2 files changed
+33−7
CHANGELOG.md+14@@ -3,6 +3,20 @@ All notable changes to the Adom Bridge Fusion 360 bridge, newest first. Canonical: https://wiki.adom.inc/adom/fusion-bridge ยท GitHub backup: `adom-inc/fusion-bridge` +## 1.13.46 (2026-10-31)++Issue #135, the real cause (checked live on Fusion 2706.1.14): ADD raises Fusion's PlacePartWorker `assetAdded`+error when the part's footprint carries no 3D package Fusion can add to the design. The same ADD lands for parts whose+footprints carry a cloud 3D package, in a new design or an imported one, from USE of the .lbr; the seed's library and+its name were not the cause.+- `fusion_schematic_run` refuses, before any ADD, a part whose footprint has no 3D package (`no_3d_package`, naming+ each part), so Fusion never raises the error. It still checks each ADD and stops at the first that did not land,+ and an assertion during the run still fails it (`fusion_assert`).+- 1.13.45's whole-library seed is reverted to the fixed parts' devices (`wholeLibrary:true` embeds them all), and+ schematic_run uses the .lbr as before; neither changed the outcome.+- A 3D package that exists but cannot be added (a WIP cloud file in another project, locally modified) still makes+ Fusion raise the error; the run then stops at that part and says so.+ ## 1.13.45 (2026-10-31) Issue #135 (Andy Engevold, AI Flow schematic_run: every ADD failed with "No part available", then Fusion's
rust/bridge/src/routing_script.py+19−7@@ -676,8 +676,22 @@ def sch_run(app, args): try: for i in range(prod.libraries.count): held.add(prod.libraries.item(i).name) except Exception: pass- used = 'design' if lbr and libname in held else ('use' if lbr else None)- if used == 'use': app.executeTextCommand("Electron.run USE '%s';" % Path(lbr).as_posix())+ used = 'use' if lbr else None+ if lbr:+ # Fusion 2706 asserts on ADD (PlacePartWorker assetAdded) when a part's footprint has no 3D+ # package it can add to the design (#135, checked live 2026-10-31: the same ADD lands when the+ # package carries a cloud 3D package). Refuse those before any ADD, naming them.+ pk3 = {pi.get('name') for q in lroot.iter('package3d') if (q.get('urn') or q.get('wip_urn')) for pi in q.iter('packageinstance')}+ no3d = []+ for c in cmds:+ m = SCH_FORMS[0][1].match(c.strip()) if isinstance(c, str) else None+ if not m: continue+ ds = next((d for d in lroot.iter('deviceset') if d.get('name').upper() == m.group(1).upper()), None)+ pkgs = {x.get('package') for x in ds.iter('device') if x.get('package')} if ds is not None else set()+ if pkgs and not (pkgs & pk3): no3d.append({'part': m.group(3), 'deviceset': m.group(1), 'footprints': sorted(pkgs)})+ if no3d:+ fail('no_3d_package', 'Fusion cannot ADD these parts: their footprints carry no 3D package (Fusion 2706 raises its PlacePartWorker assetAdded error on such an ADD): %s. Nothing was added.' % ', '.join('%s (%s)' % (x['part'], x['deviceset']) for x in no3d))+ app.executeTextCommand("Electron.run USE '%s';" % Path(lbr).as_posix()) pause = min(max(float(args.get('pauseMs', 0)), 0), 3000) / 1000.0 for c in cmds: c = c.strip()@@ -847,11 +861,9 @@ def board_seed(args): lib = root.find('drawing/library'); LIB = Path(lbr).stem; lib.set('name', LIB) fixed = args.get('fixed') or [] keep = {str(f.get('deviceset')).upper() for f in fixed}- # the WHOLE library goes into the design by default: schematic_run ADDs every other part from the- # library the design holds, because on Fusion 2706 USE of a .lbr on disk is accepted but ADD then- # finds nothing (issue #135: every ADD failed, "No part available"). wholeLibrary:false keeps only- # the fixed parts' devices, as before.- if args.get('wholeLibrary') is False:+ # the fixed parts' devices only (wholeLibrary:true embeds every one); schematic_run ADDs the rest+ # through USE of the .lbr, which works when each part carries an addable 3D package (#135)+ if args.get('wholeLibrary') is not True: for d in list(lib.find('devicesets')): if d.get('name').upper() not in keep: lib.find('devicesets').remove(d) used_sym = {g.get('symbol') for d in lib.iter('deviceset') for g in d.iter('gate')}