printhive/tools/threemf_info.py
dlawler489 f3a69c82ec Open models in your slicer and drag files out
- Settings → Slicer: pick Bambu Studio, OrcaSlicer, PrusaSlicer, Cura, a
  custom open-link template, or plain download (remembered per browser)
- Bambu Studio / OrcaSlicer launch via their URL schemes with a 10-minute
  signed download link (/dl/<token>/<name>) that needs no session cookie
- PrusaSlicer and Cura fall back to a download (they can't open our links)
- 3MF projects report which app saved them; opening one in a different
  slicer asks first
- "slicer" action on every file row and archive entry
- Drag model cards (file, or zip of all files) and file/entry rows out to
  the desktop via Chromium's DownloadURL

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 09:15:37 +10:00

45 lines
1.5 KiB
Python

#!/usr/bin/env python3
"""Print a 3MF project's plates and filaments as JSON, without loading geometry.
Usage: threemf_info.py <file.3mf> [--images DIR]
With --images, each plate's preview is written to DIR/<n>.png and DIR/<n>-small.png.
"""
import argparse
import json
import os
import zipfile
import threemf_stream
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("input")
parser.add_argument("--images")
args = parser.parse_args()
try:
project = threemf_stream.read_project(args.input)
if args.images and project["plates"]:
os.makedirs(args.images, exist_ok=True)
with zipfile.ZipFile(args.input) as z:
for plate in project["plates"]:
for name, suffix in ((plate["thumbnail"], ""), (plate["thumbnail_small"], "-small")):
if name:
with open(os.path.join(args.images, f"{plate['index']}{suffix}.png"), "wb") as out:
out.write(z.read(name))
except Exception as exc:
print(json.dumps({"error": f"could not read 3MF: {str(exc)[:200]}"}))
return 1
print(json.dumps({
"application": project["application"],
"plates": [{"index": p["index"], "name": p["name"], "objectCount": len(p["objects"]),
"thumbnail": bool(p["thumbnail"] or p["thumbnail_small"])} for p in project["plates"]],
"filaments": project["filaments"],
}))
return 0
if __name__ == "__main__":
raise SystemExit(main())