← Commit history

v0.9.107: kicad_install_footprint gains model (3D .step/.wrl, base64) -> installs to 3dmodels/Adom + wires the footprint's (model) ref; uninstall removes 3dmodels/Adom

John Lauer ·fbdc6b38da ·2mo ago ·parent 82dee79
6 files changed +48−8
BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.9.106+0.9.107
adom-bridge-kicad-manifest.json+5−5
@@ -1,15 +1,15 @@ {   "manifest_version": 1,   "name": "kicad",-  "version": "0.9.106",-  "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.106/adom-bridge-kicad-v0.9.106.zip",-  "sha256": "c0a6ab963c2544b796b32184f211d8decddb7786df984994ca91f92362253d98",-  "size": 396973,+  "version": "0.9.107",+  "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.107/adom-bridge-kicad-v0.9.107.zip",+  "sha256": "ec2619331181d5a912a7f6e80674215f0695af32002a116346324877f536830b",+  "size": 397599,   "verbPrefixes": [     "kicad_"   ],   "healthEndpoint": "/status",-  "released_at": "2026-08-15T10:18:25Z",+  "released_at": "2026-08-15T10:56:53Z",   "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png",   "languages": [     "Python",
adom-bridge-kicad-v0.9.107.zipadded
⋯ 1 unchanged line ⋯
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "kicad",   "displayName": "KiCad EDA",-  "version": "0.9.106",+  "version": "0.9.107",   "description": "Reverse bridge for KiCad \u2014 board/schematic introspection, lint via kicad-cli, plugin install, multi-instance probe, in-process DRC.",   "homepage": "https://wiki.adom.inc/adom/adom-bridge",   "author": "Adom Inc.",
handlers/install_footprint.py+38
@@ -35,6 +35,12 @@ def handle_install_footprint(kicad_info: dict, args: dict) -> dict:             - fileContent (required): Base64-encoded .kicad_mod file content             - footprintName (optional): Specific footprint to open in the editor             - openEditor (optional): Whether to open Footprint Editor (default: true)+            - model (optional): {fileName, fileContent} — a 3D model (.step/.wrl,+              base64, binary-safe) installed to Documents/KiCad/<ver>/3dmodels/Adom/+              and wired into the footprint's (model ...) reference (injected if the+              footprint has none), so kicad_show_3d_chip renders the part. Wiki+              component pages ship symbol+footprint+step; without this the step+              was dropped and the 3D view came up empty.      Returns:         Dict with:@@ -101,6 +107,35 @@ def handle_install_footprint(kicad_info: dict, args: dict) -> dict:     pretty_dir = fp_dir / ADOM_FP_DIR_NAME     pretty_dir.mkdir(parents=True, exist_ok=True) +    # --- Step 2b: optional 3D model (install + wire into the footprint) ---++    model = args.get("model") or {}+    model_installed = ""+    if model.get("fileName") and model.get("fileContent"):+        try:+            model_bytes = base64.b64decode(model["fileContent"])+        except Exception as e:+            return {"success": False, "error": f"Failed to decode model.fileContent: {e}"}+        models_dir = Path(user_dir) / "3dmodels" / "Adom"+        models_dir.mkdir(parents=True, exist_ok=True)+        model_path = models_dir / Path(model["fileName"]).name+        model_path.write_bytes(model_bytes)+        model_installed = str(model_path)+        model_uri = str(model_path).replace("\\", "/")+        if "(model " in footprint_text:+            import re+            footprint_text = re.sub(r'\(model\s+"[^"]*"', f'(model "{model_uri}"',+                                    footprint_text, count=1)+        else:+            body = footprint_text.rstrip()+            close = body.rfind(")")+            footprint_text = (body[:close]+                              + f'  (model "{model_uri}"\n'+                              + "    (offset (xyz 0 0 0))\n"+                              + "    (scale (xyz 1 1 1))\n"+                              + "    (rotate (xyz 0 0 0))\n"+                              + "  )\n)\n")+     # The .kicad_mod file must be named to match the footprint name inside it     dest_file = pretty_dir / f"{footprint_name}.kicad_mod"     dest_file.write_text(footprint_text, encoding="utf-8")@@ -144,6 +179,8 @@ def handle_install_footprint(kicad_info: dict, args: dict) -> dict:     ]     if registered:         output_parts.append("registered in fp-lib-table")+    if model_installed:+        output_parts.append(f"3D model installed + referenced: {model_installed}")     if editor_opened:         output_parts.append(f"Footprint Editor: {editor_output}")     elif open_editor:@@ -156,4 +193,5 @@ def handle_install_footprint(kicad_info: dict, args: dict) -> dict:         "footprintName": footprint_name,         "libraryName": ADOM_FP_LIB_NAME,         "editorOpened": editor_opened,+        "model3d": model_installed or None,     }
handlers/uninstall.py+3−1
@@ -18,7 +18,8 @@ What this bridge creates (and this verb removes):   2. Adom symbol lib — Documents/KiCad/<ver>/symbols/Adom.kicad_sym + its      "Adom" row in %APPDATA%/kicad/<ver>/sym-lib-table   3. Adom footprints — Documents/KiCad/<ver>/footprints/Adom.pretty/ + its-     "Adom" row in fp-lib-table+     "Adom" row in fp-lib-table + Documents/KiCad/<ver>/3dmodels/Adom/+     (3D models delivered via install_footprint's model arg, 0.9.107)   4. Mesa fallback   — opengl32.dll / libgallium_wgl.dll / dxil.dll (+ *.local)      that kicad_enable_software_opengl dropped into a KiCad bin/ (KiCad never      ships these in bin, so presence == our deploy)@@ -155,6 +156,7 @@ def handle_uninstall(kicad_info: dict, args: dict) -> dict:                 rm_file(f, "plugin pycache")         rm_file(ver_dir / "symbols" / "Adom.kicad_sym", "Adom symbol library")         rm_tree(ver_dir / "footprints" / "Adom.pretty", "Adom footprint library")+        rm_tree(ver_dir / "3dmodels" / "Adom", "Adom 3D model library")      # lib-table rows (sym + fp) in every config version     try: