mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-07 12:31:56 +00:00
e4844753cb9a836cda170d2a416412b3ca875ff1
93 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9cd655259d |
Profiler: commands, feature evaluation, io; diagnostics.profile; CLI --profile
- Session::execute is a command span; Model::evaluate and each feature computed (by its type) are spans; io's import, export and design read/write too; the STEP reader's topology, pcurves and solid record. - diagnostics.profile (contract + output schema): report, start/stop, reset, Chrome trace file. - A STEP/IGES import's reply carries its own profile while recording. - Every app compiles the profiler in by default (feature `profile`); SOLIDCRAFT_PROFILE=1 starts it. - solidcraft-cli run/eval/bench-open --profile print the table on stderr, --profile-out writes the trace; run --profile works on designs and STEP files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
c854239d18 |
doc, engine: solid.fillet setbacks: [{vertex, distance}]
FeatureKind::Fillet gains setbacks (serde default: none, omitted when empty), each a corner vertex and a length expression; a fillet with setbacks is evaluated by kernel::fillet_setback. Constant-radius exact fillets with rolling corners only (refused otherwise, in the command and in evaluation). One distance per corner: SMLib keeps one setback per corner, not per edge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
9a79588575 |
doc, engine, ui: placing the model returns its error; placements are checked where they are set
doc: world_state, world_state_reusing, state_in_frame_at, state_in_frame, face_point_state, face_point_names and construction_state return Result. A body that could not be placed, a frame that could not be inverted, a sketch plane or thread axis that did not survive the placement, or a failed placing worker used to leave things where they were without a word; now the call fails with what could not be placed. is_placement is the one test of an occurrence's placement (finite, a rotation that does not mirror, a translation within 1e9 mm). Opening a design names every occurrence that fails it; add_occurrence refuses one; a joint solution that would place an occurrence outside one is not applied and the joints placing it report it. engine: Session::world_state returns Result and keeps a failure in its cache as it keeps a placed model. bounds, home_camera, open_sketch_plane, the scene builders, the world previews, frames::to_local and auto_operation pass the error on; helpers answering "not found" take the placed model from their caller. Commands setting a placement check it (valid_position, exploded view, fastener at a point, STEP insert matrix). ui: panels, picks and hovers read the session's placed model through open_meshing::session_world; a model that cannot be placed shows no placed bodies, and the viewport says why across its bottom. Pictures and the control channel report the error. cli, mcp: snapshots, renders, benches and the oracle report the error; the kernel-case rig records it as the case's failure. Tests read the new Results with unwrap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017itGh5fpMEousnZ91cYcVt |
||
|
|
84bd2daadc |
doc, engine, kernel: solid.fillet and solid.chamfer round each picked edge's tangent chain by default
The kernel blends exactly the edges given; the feature's tangent_chain (default true, saved only when false: pending format note blend-tangent-chain) expands each pick to its tangent chain (kernel::tangent_chain) before the kernel call. A variable or spline round takes its edge alone. Scripts and MCP passing one pick get the chain again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017itGh5fpMEousnZ91cYcVt |
||
|
|
42997a62ed |
WIP kernel: Body::mesh(&MeshTolerance) as the one mesher (does not build yet)
Body::mesh / mesh_plan / mesh_of and MeshTolerance (chord, display, display_of, export_of) replace tessellate, tessellate_with, display_mesh*, display_plan*, reference_display_mesh_angular; every caller in kernel, doc, engine, io, ui-egui, gpu and the CLI renamed mechanically; the truck-mesher fallback, mesh_shells*, refined* removed; Body::new orients from the planner; truck-meshalgo dropped from Cargo.toml with the tests of its hooks. Still to fix: trait imports in tess/*, splitface/lumps/preview/step_in/boolean_record meshalgo uses, measure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017itGh5fpMEousnZ91cYcVt |
||
|
|
2f4d6acacb |
brep: working tolerance, golden v5 records, cache producer 4
Edges, vertices and the body carry the face tolerance (10^-6 of the body's size, at least 10^-5 mm): truck's traced intersection edges sit about 1e-6 mm off their surfaces, so the linear tolerance is too tight for a pcurve to lift onto them. The box-and-fillet golden fixture is the schema 4 envelope now (NATIVE_BREP_BLESS=1 rewrites it), and the adapter tests cover a pair of lumps. The model cache's producer revision becomes solidcraft-truck-adapter/4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QWhMwdqJYQKQq8RCLSL1LT |
||
|
|
739e442824 |
Links: ask before following a design's network paths (#7372)
A path a design names (a linked design, a sketch text's font file) now goes through one rule before any file call: a network location is reached only once its server is allowed, a device path never. Update Links and Open Linked Design ask first (Allow once / Always allow this server / Cancel); Preferences > Design lists the allowed servers and can allow every network location. component.links reports such a link's found as unknown with a reason, without looking for it. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
b2525ed34e |
Tests: the six timing assertions do not depend on the wall clock (#6917) (#6925)
* claim: #6917 * Tests: the six timing assertions do not depend on the wall clock (#6917) Six tests asserted on the wall clock. Their result depended on how loaded the machine was and not only on the code under test: they passed on an idle machine and failed when the test binaries ran beside each other, which is how the suite runs (`cargo xtask test` starts every test binary at once). CONTRIBUTING.md:196 says it: "Tests run beside each other on a busy machine, so a test must not depend on wall-clock timing." The change is confined to the six test files the issue names: - geom: the tangent chain of a helix is a ratio (750 pieces against 3 000) instead of a limit of 200 ms. - io: the placement budget is spent inside the reader, so the clock is gone. - ui-egui: the classification of many faces is a ratio (900 against 3 600) instead of a limit of 10 s. - engine: the clearance measurement drops its 30 s limit; the boolean that gives up reports itself. - engine: the fillet beside a modelled thread is a ratio (a 1 mm thread against an 8 mm one) instead of a limit of 30 s. - ui-egui: the window frame budget goes from 250 ms to 20 s, the limit #6072 gave its own probe. The helper is the one #649 wrote, copied into the crates that need it, with the noise of a run as a parameter. |
||
|
|
710b7a664e |
Save a mesh larger than the design file once it is compressed (#6600) (#6701)
* claim: #6600 Co-authored-by: Cursor <cursoragent@cursor.com> * Save an imported mesh that only fits after compression (#6600) The design file limit was applied to the mesh before Deflate, so a mesh that had already loaded could not be saved or autosaved. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: validate and version large mesh saves (#6600) --------- Co-authored-by: Colin Faulkingham <colinfaulkingham@Colins-Mac-mini.local> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
a3890b3bd5 |
Open a linked part from its assembly Browser row (#2348) (#2349)
* claim: #2348 * Open linked designs from assembly browser * claim: #2348 * Test linked design action with multiple components selected * Fix linked design lookup in browser storage and translate its menu action * Add Turn Up Axis to complete UI catalogs * Keep browser DXF download after linked-design checks |
||
|
|
ceed604498 |
Mesh export: a quality choice, so small round features get enough sides (#4747) (#4773)
Every STL, OBJ and 3MF export meshed each body with a chord tolerance of 2e-4 of its size, with no way to ask for finer: a 3 mm hole in a 200 mm part came out with about 14 sides. file.export and file.save_mesh take `quality`: standard (as before, the default), fine (5e-5) or finest (1e-5), and Save As Mesh has a Quality row, remembered like its format. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
0312808b92 |
DXF: reject non-BMP text instead of replacing it (#5056) (#5709)
* claim: #5056 * fix: reject unsupported Unicode in DXF text (#5056) * fix: adapt new DXF callers to fallible writer (#5056) |
||
|
|
cc1e654690 |
Warn when a design is open elsewhere or changed on disk (#5467) (#5468)
* claim: #5467 * Warn when a design is open elsewhere or changed on disk (#5467) The desktop app keeps a lock file next to each open design (.~<file>.lock: computer, user, version, opened and refreshed times), refreshes it every minute and removes it on close; a lock not refreshed for three minutes is stale and ignored. Opening a design that another SolidCraft has open asks: Open Read-Only, Open Anyway or Cancel. A read-only design saves only to another file. A design remembers its file's size and modification time when it is opened or saved. Save over a file another program or computer changed since asks: Save a Copy (the default), Overwrite or Cancel. Programmatic calls never ask: doc.open reports open_elsewhere and takes read_only, and file.save over a changed file returns an error until it is given overwrite: true. ui.documents answers both questions. |
||
|
|
b88673f366 |
Model cache: each sheet body is written once, not with every state (#6152)
* Test: a saved model keeps each sheet body once A sheet-metal design wrote its sheet bodies again with every later feature's state in the saved model: each feature that leaves the sheet alone (a box beside it) adds more than the whole sheet to the records. A design of many features after its sheet metal passed the cache's 32 MiB manifest limit that way and kept only some of its states (#3220). The test also opens the saved file and wants the sheets taken from it as evaluated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PsiqyXWBFGTCX9J51bhysc * Model cache: each sheet body is written once, not with every state Problem: a saved model writes every feature's state, and each state wrote its sheet bodies in full; most features leave the sheets as they were, so a sheet-metal design of many features repeated them over and over (a 280-feature part: 30.5 MB of manifest, 29.6 MB of it 69 distinct sheet records written 243 times). Past the manifest's 32 MiB limit the save thinned the cache (#3220) and opening evaluated the left-out features again, although the distinct data was small. Solution: the records keep a list of sheet bodies, each written once; a state names its sheets by their place in it, as it already does for bodies and sketches. A thinned model keeps the whole list and counts it once against its budget; the reader counts sheets with the bodies and sketches a state holds; the cache format is now /4 (an older cache is a miss). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PsiqyXWBFGTCX9J51bhysc --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
b201c283c7 |
Model-cache tests trust an unknown source commit, so they pass without git (#4221)
Fixes #4045 |
||
|
|
96661111f9 |
OBJ export shares vertices and keeps body names as written (#4462)
Fixes #4451 |
||
|
|
b00a1e87f4 |
Insert SVG: refuse geometry scaled to infinity, and bound the profile grid (#5020) (#5025)
* claim: #5020 * Insert SVG: refuse geometry scaled to infinity, and bound the profile grid (#5020) A transform such as scale(1e308) turned a circle's radius into infinity. The SVG reader now refuses non-finite transforms and geometry with a clear error, and Grid::cells in the profile finder uses checked arithmetic, so an infinite or huge box is checked against all shapes instead of wrapping the cell count and allocating until memory runs out. * Insert SVG: refuse lines with infinite ends; fix the grid test's cell count A line whose transformed ends are infinite was dropped silently, because the distance between them is NaN. It is now refused as out of range, like curves. The new grid test expected one cell for a box spanning its own one-box grid; such a box touches the 2 x 2 cells at its corners, so it expects 4. |
||
|
|
9e6e0b8df1 |
Render workspace: complete experimental ribbon, resources and effects integration (#5493) (#5494)
* wip(render): reconcile completed material and image pipeline source with 0.20 (#5493) Source-only integration reference for staged review, not a merge-ready aggregate. Donor: 0xlillith/solidcraft@aea20b0115. Upstream: |
||
|
|
b7b25f9e2b |
Render workspace: first basic delivery to main (#6050)
* Normalize UI container violation paths across platforms (#5599) Report repository-relative paths with forward slashes so diagnostics and the existing nested-package regression assertions agree on Windows and Unix. Keep the container detection rules unchanged. Validation: official ui-containers gate and all seven focused xtask tests passed; rustfmt and diff checks passed. Only xtask/dependencies were compiled; no application build or heavy tests. (cherry picked from commit |
||
|
|
612d9d08dd |
cadmpeg 0.6.3: FreeCAD and Rhino import in the browser too (#4482)
cadmpeg 0.6.3 is pure Rust (ruzstd instead of the zstd C library, zip 9), so solidcraft-io depends on it on every target and the wasm build reads .FCStd and .3dm files like the desktop app. The browser's file pickers offer them. 0.6.3 replaces DecodeOptions::container_only with a decode depth; ask for Geometry, what its STEP writer reads. zip 8 leaves the tree, and with it the three cargo-deny advisory exceptions kept for it. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
fa2c1c31f6 |
3MF import: name a Bambu Studio project's bodies after its objects (#3858) (#3859)
* claim: #3858 (3MF import: names from a Bambu Studio project) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * 3MF import: name a Bambu Studio project's bodies after its objects (#3858) Bambu Studio leaves the name off the root model's objects and keeps it in Metadata/model_settings.config (<config><object id="N"><metadata key="name">), so every object of a project came in as Mesh1, Mesh2, ... A build item whose root object has no name of its own now takes the object's name from those settings. A name in the model still comes first, and part names, other settings and objects of other model parts are left alone. The settings are read only when a body needs a name, within what the model parts left of the 1 GB budget. Settings that can't be read (malformed, nested too deeply, too large) never fail the import: the bodies keep the generic names, with a warning saying why. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Tyler Chiriboga <18270301+Tyler-Chiriboga@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
1d9bdb1ca3 |
FreeCAD/Rhino import: decode caps with room for detailed parts (#1783) (#3209)
* claim: #1783 * FreeCAD/Rhino import: decode caps with room for detailed parts (#1783) cadmpeg decoded FreeCAD and Rhino files under its service profile, whose million collection items and 2.56e8 work units a detailed part (a sprocket, a threaded rod, a part with a few hundred faces) runs past: the import was refused with "resource limit on CollectionItems: BudgetExceeded". Allow 8 million items and 2e9 work units, half of cadmpeg's desktop profile; the input-size cap stays SolidCraft's STEP limit and every other cap stays at the service profile's. decoding_is_capped checks the two raised caps (and that they stay below the desktop profile's) and that every other cap is still the service one. Fixes #1783 |
||
|
|
e8a6a5d3ff |
DXF: write and read a Bézier at its own degree (#5269) (#5281)
* claim: #5269 * DXF: write and read a Bézier at its own degree (#5269) The DXF writer and reader held a spline's degree to 7, the value MAX_BEZIER_DEGREE had before #1642 raised it to 9. A G4 blend (one Bézier of degree 9) was written as a degree-7 SPLINE over its first 8 control points, so a flat pattern's cut-out stopped 4.444 mm short in the file. - seg_shape takes its limit from MAX_BEZIER_DEGREE: a Bézier is written whole, at its own degree. - read_dxf reads SPLINE degrees 1 to MAX_BEZIER_DEGREE, the degrees a sketch spline takes. - Tests: every Bézier degree 4 to 9, a degree-9 round trip, the reader's degrees, hostile SPLINE degrees and too few control points, the G4 cut-out exported and read back with its areas, and a degree-9 SPLINE with 2 to 10 points inserted into a sketch. Fixes #5269 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
e33c371e99 |
Model cache: thin the checkpoints of a design too big for its file instead of leaving the cache out (#3220) (#4882)
* claim: #3220 * Model cache: keep fewer states of a design too big for its file instead of none (#3220) A model cache over the container's budget keeps the final state, then the slowest features' states while the bodies they add fit (a body several states hold counts once), and is left out only when not even the final state fits. Opening evaluates just the features whose state the file left out, each from the state before it, so the model is whole afterwards. * Model cache: keep each encoded body apart, copy only what a cache stores Encoding a model too big for its file no longer copies every distinct body into one buffer before thinning: the payload is copied from the encodings once its size fits, so saving holds no more than before. * Model cache tests: canonical runs in the timeline fixture; rustfmt * Model cache: count the records a thinned cache keeps; always try the final state Thinning counted only the bodies, so a model of many copies of one part (records, not bodies, filling the room) shrank its budget to nothing and saved no cache although its final state fitted. The choice now counts the records of what it keeps, always keeps the final state, and says what it counted, so each retry keeps less and the final state alone is always tried. * docs: a thinned model cache counts its records and always tries the final state * Model cache test: the slowest feature's state holds bodies 16 to 23 * Model cache: thinned opens with fingerprints that read the state before a feature Since #3397 a feature's fingerprint reads where the bodies before it lie. After a state the file left out, adopt takes the saved fingerprint and the evaluation that works the state out checks it. A result evaluated ahead is never taken as one the file left out. The thinned round trips include the placed components' design, whose cut reads those placements. --------- Co-authored-by: MateuszSychXpl <151755914+MateuszSychXpl@users.noreply.github.com> |
||
|
|
17f0d6bc68 |
Format registry: one table of formats, extensions and options (#5215) (#5217)
* Add the format registry: one table of formats, extensions and options in crates/io. The hosts' Open-dialog filters and the web accept list derive from it, and registry tests pin it to the path predicates and the command docs. * Fix format-registry tests that compared FormatSpec without Eq. assert_eq on Option<&FormatSpec> does not compile; the none cases only need is_none, matching the other rows that compare ids. |
||
|
|
3b982ca371 |
Prevent deleted item IDs from being reused (#1016) (#3641)
* claim: #1016 * Prevent deleted design item IDs from being reused |
||
|
|
4dc1828138 |
Imported meshes: share their triangles between document copies (#4673) (#4675)
Every edit clones the document for undo, and `MeshData`'s positions and triangles (plain `Vec`s) were copied with it: ~165 MB a command for a 2 M- triangle STL. They are now `Arc<[f64]>` and `Arc<[u32]>`, shared by clones; the few places that rewrite them build new arrays. Saved designs are unchanged (an `Arc<[T]>` serializes as the array). Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
5a9e771cc9 |
io: the 3MF and DXF budget tests do not check wall-clock time (#2998) (#2999)
* claim: #2998 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * io: the 3MF and DXF budget tests do not check wall-clock time nested_fan_out_of_empty_objects_is_bounded spends about 20 million visits reaching the work budget: 1.5 s alone, up to 40 s and more when every test binary runs at once, past its 30 s limit. The time checks run only after the reader returns, so a missing budget hangs these tests with or without them; the error, the empty geometry and the three vertices per placement are what show the budgets work. CONTRIBUTING.md: a test must not depend on wall-clock timing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: kezmdor <15539254+kezmdor@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
164554edba |
3MF import: production extension review follow-ups (#2089) (#3628)
* claim: #2089 (3MF production extension: review follow-ups) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * 3MF import: production extension review follow-ups (#2089) Follow-ups from the review of #2127: - Only the root model's build is read; other parts' build sections are ignored as the spec asks (a slicer's child build pointing at a thumbnail no longer matters). - A model part that can't be read fails only the placements that need it; the package-wide caps (part names, 1 GB of model XML) still refuse the package. The root XML is dropped once parsed and each part is read against the remaining budget. - Loops are reported apart from depth, keyed by (part, object). - Messages name parts as written; objects are kept in id order so parts are read in the same order every run; %XX escapes in part names are decoded; the model unit is a local of the parser. - Tests: a component without p:path stays in its part (T1), the same id in two parts is no loop (T2), a slicer-shaped project (T3), the placement budget across parts (T4), a loop through three parts and a chain past the depth cap (T5), broken parts and child builds (T6), escaped names; the hostile-parts test asserts its messages; the mutation test also mutates the parts' XML and zips it again. - Guide: what slicer-only data is not read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Tyler Chiriboga <18270301+Tyler-Chiriboga@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
38c710e72e |
Save designs with large STEP imports: compress the STEP part (#3221) (#3285)
* claim: #3221 * Save designs with large STEP imports: compress the STEP part (#3221) A STEP between 256 and 512 MiB imported fine but could not be saved: a design stored the STEP text uncompressed, and a design part is capped at 256 MiB. STEP sources are now always Deflated (level 2), may be as large as an import accepts inside the file, and an import that could not be saved even compressed is refused with a clear message. Reading stops at a part's declared size, so a decompression bomb is refused early. |
||
|
|
26c0c19ef7 |
Preserve imported part names and IGES assembly structure (#1609)
Build on #1426's import components and nested STEP assembly instances. Replace placeholder solid labels with meaningful part or instance names. Translate IGES groups and subfigure instances through the existing STEP component path, preserving nesting and placements and sewing surfaces within each group. Bound assembly walks and reuse work buffers. Related to: - tangency-labs/solidcraft#1386 - tangency-labs/solidcraft#1426 Co-authored-by: Codex <noreply@openai.com> |
||
|
|
e98e065584 |
Open saved designs from the model they were saved with (#3053) (#3102)
* WIP: adopt the saved model on open (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * WIP: tests * WIP: bench-open opens as Open does * docs: opening from the saved model * Tests: an edit after opening evaluates from the feature it changes * clippy * Read SOLIDCRAFT_NO_MODEL_CACHE through the env helper * Open: no picture from the model when the model itself opens; cancel test evaluates * Saved model: bodies passed through found without writing their record; states list runs of bodies * Adopted results go into the evaluation cache: an undone edit, or the marker rolled forward, takes them again * Model cache size guard: the saved model's writer --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
46a0b25280 |
STEP import: CJK names read back whole (#2344) (#2347)
Adjacent \X2\...\X0\ runs, as step_out writes one per character, now decode: the backslash opening the next run was pushed as a literal, so a name exported as 圆角 came back as 圆\X2\89D2\X0\ (also every linked component insert, which round-trips through STEP). STEP and IGES bytes that are not UTF-8 are decoded in their detected legacy encoding (chardetng + encoding_rs) instead of from_utf8_lossy, so GBK or Shift_JIS names from vendor files no longer turn into U+FFFD. Co-authored-by: bherbruck <brennen.herbruck@gmail.com> |
||
|
|
d0afc31632 |
Save the evaluated model with every design: exact, stored once, scaled caps (#3053) (#3093)
* Model cache written by default: exact bodies, stored once, scaled caps (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * bench-open: say why bodies were not kept * Exact planes and revolutions; budgets for large bodies (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Native B-rep: rebuild shells as the kernel made them (closed and seam edges) (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: the model cache and the exact native B-rep (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * bench-open: time a save without the cache too * Model cache entries are Deflate-compressed (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Model cache: one that does not fit the design file is left out, never a failed save (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
b0b59480eb |
Joints: relations that tie part of a placement (#2497)
Joints can tie part of a placement: parallel, angle, point on plane and more (#2496). |
||
|
|
4a4eb59788 |
3MF import: read objects in other model parts (production extension) (#2089) (#2127)
* claim: #2089 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * 3MF import: read objects in other model parts (production extension) (#2089) Slicers save multi-part projects with the 3MF Production extension: the root model's objects are components with `p:path` naming another model part of the package, which holds the meshes. The reader skipped those components and build items, so such files did not open at all. Components and build items now keep the part they name, and the parts objects name are read once each (looked up through an index of the zip entries), with the number of part names and their total size capped. Each part's unit is applied as it is read, so parts in different units fit together. Cycle detection keys on (part, object), so parts that place each other in a loop are refused. Tests: components and build items in another part, part names in any case, a part in centimetres under a root in millimetres, and hostile packages (missing part, a path out of the package, an empty path, an unknown object, a part that is no model, a loop between parts, more part names than a package can hold). The 3MF mutation fuzz also runs on a production-extension package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * 3MF import: count every placement toward the budget (#2089) An object that only places other objects added nothing to the triangle budget, so a few objects each placing hundreds of components multiplied at every level up to the depth cap (300 components, 3 levels: about 1 s; deeper never finished). That was already true for one model part and now reaches across parts. Every placement now costs at least one unit, so such a file stops at the budget. Test: six levels of 300 components over an empty object (300^6 placements) stop with a budget error in well under a second; without the change the test does not finish. Suggested in review by @jyviko. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Tyler Chiriboga <18270301+Tyler-Chiriboga@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: bherbruck <brennen.herbruck@gmail.com> |
||
|
|
c4d2ae87ee |
deps: zip 3.0.0 → 9.0.4 (RUSTSEC-2026-0367, -0368, -0369) (#1971)
Thanks @jyviko. |
||
|
|
30ca43de7d |
io: every file reader survives deterministic mutation; glTF refuses a POSITION naming a missing accessor (#469) (#1923)
Thanks @CamWight. |
||
|
|
78c6364b02 |
Saving to a network share on macOS: fall back to a plain fsync (#1741)
Thanks @onembyte. |
||
|
|
713111d9df |
STEP export: an inserted assembly's nested parts are placed once (#1895)
Thanks @NOWN-DEV. |
||
|
|
2c020dbcbc |
Revert #1682 (three-axis milling) (#1715)
Thanks @bherbruck. |
||
|
|
737c9358d0 |
Add three-axis milling with independent CAM and Fusion validation (#1682)
Thanks @CypherNaught-0x. |
||
|
|
2ae21143ee |
Motion animation export: a study or a joint drive as an animated GIF (#1680)
Thanks @SychPL. |
||
|
|
bbd4f29ebb |
Class-A surfacing 3/3: blend curves, curved-edge fillets, the G2 corner and continuity analysis (#1642)
Thanks @midasdf. |
||
|
|
44968dbfe6 |
Feature fields: a type for each role (Expr, BodyName, FacePick…) (#1273)
Thanks @jijinbei. |
||
|
|
c361630954 |
Export the current 3D view as 2D DXF with optional hidden lines (#1449)
Adds File > Export > Current View as DXF: the visible bodies projected from the current camera onto 2D LINE/LWPOLYLINE entities, with hidden edges omitted or dashed. Co-authored-by: cronos <19868002+crono2250@users.noreply.github.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> |
||
|
|
78242d67d1 |
Import FreeCAD and Rhino files through cadmpeg (#1435)
FreeCAD .FCStd and Rhino .3dm files open, insert and drop like STEP and IGES: cadmpeg (Apache-2.0, pinned =0.6.1, native builds only) detects the format, decodes it under its service resource caps, validates the model and writes it as STEP AP214, which becomes an Import feature in a new component named after the file, with the up and names options. Only the fcstd, rhino and step codecs are compiled in (no default features). ACIS is left out: cadmpeg's sat codec is a ShapeManager stream decoder. native_cad.rs is the single importer seam. Self-made FreeCAD and Rhino box fixtures, hostile-input, ZIP-bomb and cap tests, engine tests for the component path; the browser build reports these formats as not supported. A note under design format 23 says an Import's file can name these formats. Co-authored-by: Jacob Oursland <jacob.oursland@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
a13124acdd |
Import glTF 2.0 files (.glb, .gltf) as mesh bodies (#1512)
glTF files open, insert and drop like 3MF/STL/OBJ: a component named after the file, the node tree as nested rigid components, repeated meshes as occurrences, metres to mm, Y up turned to Z up by default (up: z keeps axes), materials as PBR appearances. Bounded, hostile-input tested reader; no new persisted data. Closes #1505. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
27529d9742 |
Imports become components; STEP assemblies as nested components (#1386) (#1426)
* Imports become components: a STEP assembly's tree as nested components (#1386) Every imported file (STEP, IGES, 3MF, STL, OBJ: inserted, dropped, opened as a design, or file.insert_step / file.insert_mesh / doc.open from scripts, the CLI and MCP) now comes in as a new component named after the file, with its Import feature inside it. A STEP assembly's products become nested components; a part placed more than once is one component with an occurrence per placement, and the Import feature skips the file's later copies (`skip`, format 21 note). The contents are held as one rigid group (rigid joints, glyphs hidden); moving an inner part is refused until component.unlock ("Unlock Contents") releases it. Y up turns the import's component. Replies report component, component_name and occurrence. Undo is one step; designs with loose imports are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep an import's rigid group hidden when the window loads the file in the background Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Import instances' skip list is format 22: format 21 ships in 0.12.0 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Catalog entries for Unlock Contents Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
d7a4a29ce3 |
Flat-pattern DXF for a laser shop: layers by role, dashed bend lines, bend notes, a file per body (#1324)
Closes #1284. sheet.export_dxf writes layers by role (OUTLINE, CUT, TEXT or ETCH, dashed BEND_UP/BEND_DOWN, optional BEND_NOTES, POCKET_<side>_Z…_MM and PERFORATION), inner contours before the outline; text: cut|etch, bend_notes and note_height, per_body files. Letters are derived from the timeline, nothing new is saved (format unchanged). I merged main in (the export's parameter list keeps main's pocket layer names). Checked on main + this branch: cargo check --workspace, the engine cmd::sheet tests (160) and the io DXF tests. |