- 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>
45 lines
1.5 KiB
Python
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())
|