← Commit history

#135: no_3d_package preflight; seed reverted

Colby Knox ·7db3320206 ·11d ago ·parent 9a987d2
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')}