Retire legacy reference data and the external command catalog (#302)
- Remove xtask/data/fusion-catalog.tsv and xtask/data/fusion-ids.tsv. - Remove the legacy command-id table (crates/engine/src/legacy_ids.rs) and its use in find_command and in the shortcut, recents and pinned-command loaders. Only SolidCraft's dotted ids name commands; any other id is an unknown command. - Boundary Fill's id becomes solid.boundary_fill. - Replace the parity report with SolidCraft's own feature checklist: `cargo xtask features` writes docs/features.md from the command registry. - docs/oracle.md, docs/step-import.md (corpus section) and docs/iges-import.md: reference results are being rebuilt on analytic and open-source (FreeCAD) values; see #292. `cargo xtask oracle` and `cargo xtask step-corpus [--iges]` write these placeholders. - AGENTS.md, CLAUDE.md, CONTRIBUTING.md, README.md, ROADMAP.md and the book describe SolidCraft as independent, with reference tests on analytic values and open-source tools, and agents do not drive or extract data from commercial CAD products. Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
c7f0139ad4
commit
3b8028a040
32 files changed
+695
-2324
No files matched your search
@@ -16,8 +16,7 @@ compatibility notes.
|
||||
|
||||
## Start every session here
|
||||
1. Read `plan/STATUS.md` (current milestone, next task), then the task in `plan/execution-plan.md`
|
||||
and the relevant `plan/architecture.md` section. Behaviour reference: `plan/fusion/`
|
||||
(`menu-tree.json` is Fusion's toolbar dump).
|
||||
and the relevant `plan/architecture.md` section.
|
||||
2. Kernel and library decisions: `plan/adr/0001-geometry-kernel.md` (what we may depend on, what
|
||||
is rejected for licence reasons).
|
||||
3. Follow the autonomous operation protocol (`plan/execution-plan.md` §6). Don't stop to ask
|
||||
@@ -42,20 +41,22 @@ People trust SolidCraft with their designs; a crash loses their work. **This out
|
||||
`#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]`.
|
||||
|
||||
## Non-negotiables
|
||||
- **Clean-room.** Fusion may be *observed* black-box (its UI, its toolbar dump, parts built in it
|
||||
and their measurements, kept under `plan/fusion/`, never committed). Never copy Autodesk icons,
|
||||
artwork, help text, tooltips, templates or materials, and never commit files produced by
|
||||
Fusion. Command ids and command names are used as identifiers only (`xtask/data/fusion-catalog.tsv`
|
||||
holds ids and names, nothing else). File formats come from public specifications. **Never read,
|
||||
copy or link GPL/LGPL/AGPL code**: OpenCASCADE, FreeCAD (incl. planegcs), SolveSpace,
|
||||
CadQuery/OCP, LibreCAD, QCAD — don't even read their sources. (`tools/freecad-oracle/` runs
|
||||
FreeCAD as a separate program through its public scripting API to compute reference values;
|
||||
- **Independent.** SolidCraft is independent. Behaviour is designed from public documentation,
|
||||
general CAD conventions and user feedback. Reference tests use analytic values and open-source
|
||||
tools. Never copy another product's code, icons, artwork, help text, tooltips, templates or
|
||||
materials. File formats come from public specifications.
|
||||
- **No commercial CAD products.** Agents must not drive, script, automate or extract data from
|
||||
commercial CAD products (Fusion, SolidWorks, Onshape, …) for this project: no test data,
|
||||
measurements, command lists, ids or files produced with them.
|
||||
- **Never read, copy or link GPL/LGPL/AGPL code**: OpenCASCADE, FreeCAD (incl. planegcs),
|
||||
SolveSpace, CadQuery/OCP, LibreCAD, QCAD — don't even read their sources. (`tools/freecad-oracle/`
|
||||
runs FreeCAD as a separate program through its public scripting API to compute reference values;
|
||||
nothing from FreeCAD is linked, vendored or shipped.) The sketch solver and the blend
|
||||
operations are our own.
|
||||
- **Assets — absolutely essential.** SolidCraft contains **no Autodesk iconography, images,
|
||||
fonts or artwork — ever.** Every icon is drawn in code (`crates/ui-egui/src/icons.rs`). Any
|
||||
file asset must be original or openly licensed and **must have a row in ATTRIBUTION.md**
|
||||
(`cargo xtask assets` enforces it). Screenshots of Autodesk software are never committed.
|
||||
- **Assets — absolutely essential.** SolidCraft contains **no iconography, images, fonts or
|
||||
artwork from commercial CAD products — ever.** Every icon is drawn in code
|
||||
(`crates/ui-egui/src/icons.rs`). Any file asset must be original or openly licensed and **must have a row in ATTRIBUTION.md**
|
||||
(`cargo xtask assets` enforces it). Screenshots of commercial CAD software are never committed.
|
||||
Breaking this rule is the most serious mistake you can make in this repo.
|
||||
- **Everything is a command.** User-visible behaviour = a command in `crates/engine/src/cmd/*`
|
||||
(`CommandSpec`: id = our own dotted, lower-case id `<area>.<thing>[.<variant>]` such as
|
||||
@@ -126,10 +127,10 @@ before the draft is verified.
|
||||
`solvecraft-cli snapshot script.json --out shot.png`, `solvecraft-cli commands`.
|
||||
- Reference tests: `cargo xtask oracle` replays `tests/oracle/*/recipe.json` and compares with
|
||||
each case's `expected.json` (analytic or FreeCAD values; writes `docs/oracle.md`). Expected
|
||||
values never come from Fusion or any other commercial CAD product.
|
||||
values never come from a commercial CAD product.
|
||||
- Build with `CARGO_TARGET_DIR=<repo>/target`. Windows: `cargo xwin build --release --target x86_64-pc-windows-msvc -p solvecraft`.
|
||||
|
||||
## Roadmap
|
||||
`ROADMAP.md` (committed) tracks status, milestones, parity and estimates. Update it whenever a
|
||||
milestone task lands. `cargo xtask parity` recomputes command parity in `docs/parity.md`;
|
||||
`cargo xtask oracle` recomputes `docs/oracle.md`.
|
||||
`ROADMAP.md` (committed) tracks status, milestones and estimates. Update it whenever a
|
||||
milestone task lands. `cargo xtask features` regenerates `docs/features.md` (SolidCraft's
|
||||
commands by area, from the registry) when commands are added or renamed.
|
||||
@@ -16,8 +16,7 @@ compatibility notes.
|
||||
|
||||
## Start every session here
|
||||
1. Read `plan/STATUS.md` (current milestone, next task), then the task in `plan/execution-plan.md`
|
||||
and the relevant `plan/architecture.md` section. Behaviour reference: `plan/fusion/`
|
||||
(`menu-tree.json` is Fusion's toolbar dump).
|
||||
and the relevant `plan/architecture.md` section.
|
||||
2. Kernel and library decisions: `plan/adr/0001-geometry-kernel.md` (what we may depend on, what
|
||||
is rejected for licence reasons).
|
||||
3. Follow the autonomous operation protocol (`plan/execution-plan.md` §6). Don't stop to ask
|
||||
@@ -42,20 +41,22 @@ People trust SolidCraft with their designs; a crash loses their work. **This out
|
||||
`#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]`.
|
||||
|
||||
## Non-negotiables
|
||||
- **Clean-room.** Fusion may be *observed* black-box (its UI, its toolbar dump, parts built in it
|
||||
and their measurements, kept under `plan/fusion/`, never committed). Never copy Autodesk icons,
|
||||
artwork, help text, tooltips, templates or materials, and never commit files produced by
|
||||
Fusion. Command ids and command names are used as identifiers only (`xtask/data/fusion-catalog.tsv`
|
||||
holds ids and names, nothing else). File formats come from public specifications. **Never read,
|
||||
copy or link GPL/LGPL/AGPL code**: OpenCASCADE, FreeCAD (incl. planegcs), SolveSpace,
|
||||
CadQuery/OCP, LibreCAD, QCAD — don't even read their sources. (`tools/freecad-oracle/` runs
|
||||
FreeCAD as a separate program through its public scripting API to compute reference values;
|
||||
- **Independent.** SolidCraft is independent. Behaviour is designed from public documentation,
|
||||
general CAD conventions and user feedback. Reference tests use analytic values and open-source
|
||||
tools. Never copy another product's code, icons, artwork, help text, tooltips, templates or
|
||||
materials. File formats come from public specifications.
|
||||
- **No commercial CAD products.** Agents must not drive, script, automate or extract data from
|
||||
commercial CAD products (Fusion, SolidWorks, Onshape, …) for this project: no test data,
|
||||
measurements, command lists, ids or files produced with them.
|
||||
- **Never read, copy or link GPL/LGPL/AGPL code**: OpenCASCADE, FreeCAD (incl. planegcs),
|
||||
SolveSpace, CadQuery/OCP, LibreCAD, QCAD — don't even read their sources. (`tools/freecad-oracle/`
|
||||
runs FreeCAD as a separate program through its public scripting API to compute reference values;
|
||||
nothing from FreeCAD is linked, vendored or shipped.) The sketch solver and the blend
|
||||
operations are our own.
|
||||
- **Assets — absolutely essential.** SolidCraft contains **no Autodesk iconography, images,
|
||||
fonts or artwork — ever.** Every icon is drawn in code (`crates/ui-egui/src/icons.rs`). Any
|
||||
file asset must be original or openly licensed and **must have a row in ATTRIBUTION.md**
|
||||
(`cargo xtask assets` enforces it). Screenshots of Autodesk software are never committed.
|
||||
- **Assets — absolutely essential.** SolidCraft contains **no iconography, images, fonts or
|
||||
artwork from commercial CAD products — ever.** Every icon is drawn in code
|
||||
(`crates/ui-egui/src/icons.rs`). Any file asset must be original or openly licensed and **must have a row in ATTRIBUTION.md**
|
||||
(`cargo xtask assets` enforces it). Screenshots of commercial CAD software are never committed.
|
||||
Breaking this rule is the most serious mistake you can make in this repo.
|
||||
- **Everything is a command.** User-visible behaviour = a command in `crates/engine/src/cmd/*`
|
||||
(`CommandSpec`: id = our own dotted, lower-case id `<area>.<thing>[.<variant>]` such as
|
||||
@@ -103,10 +104,10 @@ before the draft is verified.
|
||||
`solvecraft-cli snapshot script.json --out shot.png`, `solvecraft-cli commands`.
|
||||
- Reference tests: `cargo xtask oracle` replays `tests/oracle/*/recipe.json` and compares with
|
||||
each case's `expected.json` (analytic or FreeCAD values; writes `docs/oracle.md`). Expected
|
||||
values never come from Fusion or any other commercial CAD product.
|
||||
values never come from a commercial CAD product.
|
||||
- Build with `CARGO_TARGET_DIR=<repo>/target`. Windows: `cargo xwin build --release --target x86_64-pc-windows-msvc -p solvecraft`.
|
||||
|
||||
## Roadmap
|
||||
`ROADMAP.md` (committed) tracks status, milestones, parity and estimates. Update it whenever a
|
||||
milestone task lands. `cargo xtask parity` recomputes command parity in `docs/parity.md`;
|
||||
`cargo xtask oracle` recomputes `docs/oracle.md`.
|
||||
`ROADMAP.md` (committed) tracks status, milestones and estimates. Update it whenever a
|
||||
milestone task lands. `cargo xtask features` regenerates `docs/features.md` (SolidCraft's
|
||||
commands by area, from the registry) when commands are added or renamed.
|
||||
+8
-5
@@ -88,13 +88,16 @@ The [README](README.md#architecture) has the layer table. The short version:
|
||||
|
||||
## Rules that aren't negotiable
|
||||
|
||||
1. **Clean-room.** We observe Fusion as a black box: its UI, how parts it builds measure, and
|
||||
what it does with a given input. We never copy Autodesk code, icons, artwork, help text,
|
||||
tooltips, templates or materials, and we never commit files Fusion produced. Command ids are
|
||||
our own (`solid.fillet`, not Fusion's internal names).
|
||||
1. **Independent.** SolidCraft is independent. Behaviour is designed from public
|
||||
documentation, general CAD conventions and user feedback. Reference tests use analytic values
|
||||
and open-source tools. We don't drive, script, automate or extract data from commercial CAD
|
||||
products, and we never copy another product's code, icons, artwork, help text, tooltips,
|
||||
templates or materials. Command ids are our own (`solid.fillet`).
|
||||
2. **No GPL/LGPL/AGPL code, not even reading it.** That rules out OpenCASCADE, FreeCAD
|
||||
(including planegcs), SolveSpace, CadQuery/OCP, LibreCAD and QCAD. SolidCraft is
|
||||
MIT OR Apache-2.0, and its solver and blends are written from the maths. Permissive
|
||||
MIT OR Apache-2.0, and its solver and blends are written from the maths. (Running an
|
||||
open-source application to get reference values for a test is fine; reading its source is
|
||||
not.) Permissive
|
||||
dependencies are fine. Note which one you're adding and why in the PR, and run
|
||||
`cargo xtask licences` so THIRD-PARTY-LICENSES.txt lists it (CI checks that it is current).
|
||||
3. **Every asset is original or openly licensed and has a row in
|
||||
|
||||
@@ -20,8 +20,8 @@ SolidCraft application feed. See [install and launch commands](https://bherbruck
|
||||
**Status: early but usable for simple parts.** 75 of 76 public reference parts
|
||||
match their analytic or FreeCAD-computed volume, area, centre of mass and bounding box
|
||||
([docs/oracle.md](docs/oracle.md)); the other is a tracked bug.
|
||||
These checks do not establish complete geometric or workflow equivalence. Feature coverage
|
||||
is tracked in [docs/parity.md](docs/parity.md) and [ROADMAP.md](ROADMAP.md).
|
||||
These checks do not establish complete geometric or workflow equivalence. The commands SolidCraft has
|
||||
are listed by area in [docs/features.md](docs/features.md); status and plans are in [ROADMAP.md](ROADMAP.md).
|
||||
Open work and known bugs are in [GitHub issues](https://github.com/bherbruck/solidcraft/issues),
|
||||
and help is welcome: see [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||
|
||||
@@ -168,6 +168,7 @@ MIT OR Apache-2.0, at your option. Developed under the
|
||||
[clean-room contribution rules](CLAUDE.md); third-party code and assets retain their
|
||||
documented licences and attribution.
|
||||
|
||||
References to other products describe workflow comparisons and benchmark provenance.
|
||||
SolidCraft is independent. Behaviour is designed from public documentation, general CAD
|
||||
conventions and user feedback. Reference tests use analytic values and open-source tools.
|
||||
SolidCraft is not affiliated with, sponsored by or endorsed by Autodesk. Autodesk and
|
||||
Fusion are trademarks of Autodesk, Inc.
|
||||
+7
-10
@@ -7,8 +7,8 @@ features → parametric timeline) as an open, pure-Rust, agent-drivable applicat
|
||||
|
||||
| Question | Answer |
|
||||
|---|---|
|
||||
| Where are we? | **M0 and M13 done; M1, M2, M5–M7, M9, M10, M14 in progress.** Sketch with solver and the full SKETCH create/modify set; extrude, revolve (two sides, symmetric, to object), fillet/chamfer (variable radius, chord length, a radius per edge, corner patches), holes, threads (cosmetic and modelled), patterns, mirror, shell (inside/outside/both), draft, loft, sweep, coil, split body and split face, delete face, construction planes, axes and points; persistent naming of faces and edges; parameters and configurations; components, joints, motion studies, exploded views; sheet metal and a plastic enclosure subset; STEP/IGES/3MF/STL/OBJ/DXF; autosave and crash recovery; desktop and browser (wasm) app, CLI, MCP server, oracle harness. |
|
||||
| Command parity (in scope) | **335 / 541 (62%)** in-scope commands; SOLID + SKETCH **188 / 291 (65%)** — [docs/parity.md](docs/parity.md); registry breadth does not establish workflow or geometric parity |
|
||||
| Where are we? | **M0 and M13 done; M1, M2, M5–M7, M9, M10, M14 in progress.** Sketch with solver and the full SKETCH create/modify set; extrude, revolve (two sides, symmetric, to object), fillet/chamfer (variable radius, chord length, a radius per edge, corner patches), holes, threads (cosmetic and modelled), patterns, mirror, shell (inside/outside/both), draft, loft, sweep, coil, split body and split face, delete face, construction planes, axes and points; persistent naming of faces and edges; parameters and configurations; components, joints, motion studies, exploded views; sheet metal and a plastic enclosure subset; STEP/IGES/3MF/STL/OBJ/DXF; autosave and crash recovery; desktop and browser (wasm) app, CLI, MCP server. |
|
||||
| Features | Every registered command by area — [docs/features.md](docs/features.md) (`cargo xtask features`); registry breadth does not establish workflow or geometric depth |
|
||||
| Reference tests | **75 / 76 parts match** — [docs/oracle.md](docs/oracle.md): public cases in `tests/oracle/` with analytic (55) or FreeCAD-computed (21) expected values, run by CI on every PR; 75-sm-bracket-holes fails (#296). |
|
||||
| Tests | Solver, profiles, kernel booleans/blends/measures, expressions, timeline, persistent naming, file formats and migrations, assemblies, sheet metal, engine end-to-end, hostile-input fuzz over every command and headless UI scenarios. `cargo xtask ci` reports the current passing counts. |
|
||||
| Gates | `cargo xtask ci`: fmt, clippy -D warnings, tests, asset attribution, layering, wasm32 build — green |
|
||||
@@ -20,8 +20,7 @@ The issue batch adds preservation of blind pockets in through cuts, associative
|
||||
offsets and plastic face placements, XZ (+Y normal) with a v6 migration preserving older
|
||||
designs, interactive angle placement, file-picker sketch imports, Home/recent controls,
|
||||
toolbar overflow, and the remaining component-frame and assembly WIP work. The enclosure
|
||||
acceptance scenarios now include board resizes; STEP reopening is automated. Inspection in
|
||||
Fusion remains an external acceptance step. See [WIP reconciliation](docs/wip-reconciliation.md).
|
||||
acceptance scenarios now include board resizes; STEP reopening is automated. See [WIP reconciliation](docs/wip-reconciliation.md).
|
||||
|
||||
In scope, in priority order:
|
||||
1. SOLID and SKETCH (now).
|
||||
@@ -38,8 +37,7 @@ In scope, in priority order:
|
||||
5. A small PLASTIC subset for enclosures, after sheet metal: Boss, Rib, Web, Lip/Groove, Snap Fit.
|
||||
|
||||
Deferred until further notice: MESH, FORM (T-splines), SURFACE beyond what solids need, PCB / 3D
|
||||
PCB / Package, Render, Animation, Simulation, Manufacture/CAM, Drawings. The parity report's
|
||||
headline counts in-scope tabs only and lists the deferred ones separately.
|
||||
PCB / Package, Render, Animation, Simulation, Manufacture/CAM, Drawings.
|
||||
|
||||
## Milestones
|
||||
|
||||
@@ -49,14 +47,13 @@ headline counts in-scope tabs only and lists the deferred ones separately.
|
||||
| M1 | Sketch depth: command coverage implemented — projection/intersect/include as linked geometry (auto-project on faces, lost-reference warnings, break link), full SKETCH create/modify set (slots, polygons, tangent arcs/circles, ellipse, fit/control splines, conic, text, trim/extend/break, fillet/chamfer, offset, mirror, patterns, move/scale, blend curve, centerline), constraints incl. curvature and polygon with over-constraint refusal, driven/arc-length/linear-diameter dimensions, AutoConstrain, DXF/SVG insert, 3D sketch curves (Project To Surface, Intersection Curve, Isoparametric Curve, Spun Profile), exact free-form profiles (B-spline/NURBS edges, any spline degree, curves cut by crossings), sweeps and pipes along 3D sketch curves, canvases and decals, curvature combs. Exact free-form Extend and certified associative offsets now preserve geometry and IDs through edits, deletion and reopen. Occurrence-frame 3D wires now store explicit coordinate spaces and retain points and analytic fits through moves, refresh, undo and reopen. Remaining workflow repairs: mixed offset junctions, legacy natural-spline seams, and damaged legacy wire links lacking frame provenance | in progress | 4 |
|
||||
| M2 | Robust modelling: coplanar booleans in the kernel, holes (placed on faces and on sketch points), threads (cosmetic, then modelled), patterns, mirror, shell, draft, split, construction geometry | in progress | 16 |
|
||||
| M3 | General fillets and chamfers (curved edges, chains, vertex blends); saddle rolling-ball surfaces now use continuous seam sections and arc-length fitting with shared contact boundaries and bounded accuracy checks | in progress | 30 |
|
||||
| M4 | Files: STEP import (done: all 29 Fusion STEP files — [docs/step-import.md](docs/step-import.md)), 3MF export and 3MF/STL import as mesh bodies (done), constant-section parametric mesh reconstruction, DXF sketches, OBJ import | in progress | 6 |
|
||||
| M4 | Files: STEP import (done — [docs/step-import.md](docs/step-import.md)), 3MF export and 3MF/STL import as mesh bodies (done), DXF sketches, OBJ import | in progress | 6 |
|
||||
| M4 | Files: STEP import (done — [docs/step-import.md](docs/step-import.md)), 3MF export and 3MF/STL import as mesh bodies (done), constant-section parametric mesh reconstruction, DXF sketches, OBJ import | in progress | 6 |
|
||||
| M5 | Persistent naming of faces and edges (plan/adr/0002): faces named from their history (sketch curve sides, caps, revolve sections, primitive sides, blends, pattern/mirror copies; split pieces numbered), edges by their faces; fillets/chamfers, sketches on faces, shell/draft/offset/replace faces, hole placements, joint origins and face appearances resolve by name first and warn when the entity split or vanished: done. sheet metal edges by base sketch line and flange side, shell inner faces, sweep and loft roles: done. Left: kernel-reported face history (exact through coincident surfaces) | in progress | 20 |
|
||||
| M6 | UI depth: selection feedback and origin (done), timeline editing (done: hover and selection highlight modifier faces, including fillets and chamfers; edit feature, history marker drag, reorder with dependency checks, suppress, rename, delete with dependents, re-resolved references; redefining selections refreshes persistent edge/face references while retaining feature identity and dimension names), right-docked dialogs (done), live previews for every feature dialog (done), keyboard-first commands with on-canvas value boxes and sketch inline dimensions (done), drag manipulators with automatic join/cut (done: extrude incl. two sides, fillet, shell, hole depth, move, pattern spacing, revolve rotator; taper handle open), dark theme (done), right-click menu with Repeat (done), measure tool (done), section analysis (done), selection filter (done), drag-solve of sketch points (done); appearance controls now preserve body/face/component targeting, named transparent looks, reuse/search and override removal; preferences | in progress | 6 |
|
||||
| M7 | Sweep, loft (incl. to a point), rib and web (to next / depth), emboss (planar faces and exact radial emboss/deboss of bounded orthogonal profiles on complete exterior cylinders/sleeves), thread (cosmetic, and modelled M3–M20 outside and inside: the ISO profile screwed in as a faceted cut), coil (smooth B-spline helical walls), pipe, pattern on path, patterns of bodies and components, replace face (parallel), align, remove, feature copy/paste: done. Unique eligible cylindrical targets are inferred for new Emboss features. Left: general curved-face emboss and exact (unfaceted) modelled threads | in progress | 12 |
|
||||
| M8 | Surface workspace | deferred | — |
|
||||
| M9 | Components and assemblies: New Component / Create Components from Bodies, active component, per-component origin/bodies/sketches/timeline entries, occurrences with transforms, Copy/Paste vs Paste New, nested Browser tree with visibility and isolate; Ground, Move/Copy of occurrences, joints (rigid, revolute, slider, cylindrical, pin-slot, planar, ball) by joint origins with limits and Drive Joints, As-built Joint, Rigid Group, Contact Sets (driving and motion studies stop where bodies in a set would pass through each other), Motion Study (joint values keyed along a timeline, playback, export of occurrence positions as JSON/CSV), Exploded views (automatic or by hand, shown without changing placements); interference, per-component physical properties; STEP with assembly structure. Physical properties now measure material-aware component/occurrence placements, descendants and repeated instances, including pending moves and body reassignment offsets; contact geometry and automatic exploded centres respect those offsets. Groundwork done: component tree, occurrences with transforms (instances, Paste New), world placement, active component as authoring frame, ground, Capture/Revert Position, moving bodies and sketches. UI: ASSEMBLE panel dialogs for New Component, Joint (snaps on faces, edges, circles and vertices; animated motion preview; offsets, flip, limits), As-built Joint, Joint Origin, Rigid Group, Drive Joints (live slider), Motion Link and Interference (overlaps shown red); joints in the timeline and the Browser | in progress | 32 |
|
||||
| M10 | Sheet metal: flange (base, edge, contour), hem, unfold/refold, convert, flat pattern + DXF, rules: done (oracle 67-76). PLASTIC enclosure subset: Boss, Rib, Web, Lip/Groove, Snap Fit, Rest, Plastic Rules (library, edit, assign; rule draft and clearance as feature defaults): done, no Fusion oracle (licence), tested against hand-computed geometry. UI: SHEET METAL and PLASTIC tabs in Fusion's layout with dialogs (live preview, Edit Feature, pre-selection) for Flange, Hem, Unfold/Refold, Convert, Sheet Metal Rules, Create Flat Pattern (flat view with bend lines, bend table CSV/JSON and DXF export with exact circle/arc/line cutouts), Boss, Lip/Groove, Snap Fit, Rest, Manage and Assign Plastic Rules; Fold (bend along a sketch line) | in progress | 36 |
|
||||
| M10 | Sheet metal: flange (base, edge, contour), hem, unfold/refold, convert, flat pattern + DXF, rules: done. PLASTIC enclosure subset: Boss, Rib, Web, Lip/Groove, Snap Fit, Rest, Plastic Rules (library, edit, assign; rule draft and clearance as feature defaults): done, tested against hand-computed geometry. UI: SHEET METAL and PLASTIC tabs in Fusion's layout with dialogs (live preview, Edit Feature, pre-selection) for Flange, Hem, Unfold/Refold, Convert, Sheet Metal Rules, Create Flat Pattern (flat view with bend lines, bend table CSV/JSON and DXF export with exact circle/arc/line cutouts), Boss, Lip/Groove, Snap Fit, Rest, Manage and Assign Plastic Rules; Fold (bend along a sketch line) | in progress | 36 |
|
||||
| M11 | 2D drawings | deferred | — |
|
||||
| M12 | Release: cross-platform packages, verification and deliberate publication implemented; original current-UI demo refreshed. Trusted distribution signing and broader performance work remain | in progress | 16 |
|
||||
| M14 | Configurations: a table of rows (parameter expressions and feature suppressions per row) switched with config.activate (undoable, all or nothing), kept through parameter renames and feature deletes (config.configure, config.table, config.column/row/activate). Per-row body materials and appearances (library looks, custom colour/opacity and clearing overrides), undoable activation and save/reopen: done. Ordered typed configuration rules, atomic validation and structured rule editing: done. Component appearance and certified semantic face style columns, atomic preview/apply and independent-copy remapping: done. Exact constructed sketch-side and immutable imported-face lineage now preserve legacy names and reject retargeting. Left: ambiguous shifted/two-sided caps | in progress | 4 |
|
||||
@@ -311,7 +308,7 @@ headline counts in-scope tabs only and lists the deferred ones separately.
|
||||
- Rolling-ball fillet accuracy: independent offset-cylinder tee references check surface
|
||||
distance, actual trimmed tessellation, supporting-cylinder contacts and tangency at two
|
||||
scales. The measured trimmed-part error is below 0.0001 mm; this is an analytic geometry
|
||||
check, not a new Fusion oracle result. Under-resolved fits return an error.
|
||||
check. Under-resolved fits return an error.
|
||||
- Contact driving checks the trajectory between clear endpoints, including linked joints,
|
||||
playback and sparse motion exports. Checks use bounded tessellation samples, not exact
|
||||
continuous collision detection; local thin walls and small details remain limitations.
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::params::{bad, bool_, expr, req_expr, str_, string_list, vec3};
|
||||
use crate::{Result, Session};
|
||||
|
||||
pub static COMMANDS: &[CommandSpec] = &[
|
||||
CommandSpec::new("SurfaceSculpt", "Boundary Fill", boundary_fill).at("SOLID", "CREATE").icon("boundary_fill").params(
|
||||
CommandSpec::new("solid.boundary_fill", "Boundary Fill", boundary_fill).at("SOLID", "CREATE").icon("boundary_fill").params(
|
||||
"tools: [bodies]; cells: [[x,y,z] a point inside each cell to fill (a cell: inside some tools, outside the rest)]; operation?: new|join|cut|intersect; remove_tools?: bool",
|
||||
),
|
||||
CommandSpec::new("solid.coil", "Coil", coil).at("SOLID", "CREATE").icon("coil").params(
|
||||
@@ -422,7 +422,7 @@ pub(super) fn snap_point(s: &Session, kind: &str, at: Vec3) -> Option<Vec3> {
|
||||
}
|
||||
|
||||
fn boundary_fill(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let cmd = "SurfaceSculpt";
|
||||
let cmd = "solid.boundary_fill";
|
||||
let tools = string_list(p, "tools");
|
||||
let st = s.model.state();
|
||||
if tools.is_empty() || tools.len() > 64 || tools.iter().any(|t| st.body(t).is_none()) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! The command registry. Ids are SolveCraft's own dotted ids (`solid.extrude`,
|
||||
//! `sketch.rectangle.two_point`); the toolbar placement (`tab`, `panel`) follows the familiar
|
||||
//! Design workspace layout. Ids used before the rename still resolve (`legacy_ids`).
|
||||
//! Design workspace layout.
|
||||
|
||||
/// The params-doc note of every command that adds sketch geometry (see `sketch::created`).
|
||||
macro_rules! created_doc {
|
||||
@@ -180,7 +180,5 @@ pub fn command_specs() -> Vec<&'static CommandSpec> {
|
||||
|
||||
pub fn find_command(id: &str) -> Option<&'static CommandSpec> {
|
||||
let all = command_specs();
|
||||
// Ids from before the rename still find their command.
|
||||
let id = crate::legacy_ids::current_id(id);
|
||||
all.iter().find(|c| c.id == id).or_else(|| all.iter().find(|c| c.id.eq_ignore_ascii_case(id))).copied()
|
||||
}
|
||||
@@ -184,7 +184,7 @@ fn base(r: &mut Rng) -> Step {
|
||||
("sketch.line", json!({"points": pts})),
|
||||
("sketch.arc.three_point", json!({"start": [0, h], "end": [0, 0], "through": [-bulge, h / 2.0]})),
|
||||
("sketch.finish", json!({})),
|
||||
("Extrude", json!({"distance": d})),
|
||||
("solid.extrude", json!({"distance": d})),
|
||||
],
|
||||
)
|
||||
}
|
||||
@@ -198,7 +198,7 @@ fn base(r: &mut Rng) -> Step {
|
||||
("sketch.create", json!({"plane": "XZ"})),
|
||||
("sketch.rectangle.two_point", json!({"p0": [r0, 0], "p1": [r1, h]})),
|
||||
("sketch.finish", json!({})),
|
||||
("Revolve", json!({"axis": "Z", "angle": angle})),
|
||||
("solid.revolve", json!({"axis": "Z", "angle": angle})),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,236 +0,0 @@
|
||||
//! Legacy migration: the command ids SolveCraft used before 2026-10-09, when many commands
|
||||
//! carried the id of the matching command in another CAD program, and the dotted ids that
|
||||
//! replaced them. This is the one place the old ids live. Old scripts, recipes, control-channel
|
||||
//! calls, saved shortcuts and toolbar layouts keep working: `find_command` and the preference
|
||||
//! loaders map an old id through `current_id`. `solvecraft-tools/rename_ids.sh` converts a
|
||||
//! worktree with this same table.
|
||||
|
||||
/// (old id, current id).
|
||||
pub const LEGACY_IDS: &[(&str, &str)] = &[
|
||||
("AsBuiltPositionsCmd", "component.revert_position"),
|
||||
("FusionCreateComponentsFromBodiesCommand", "component.from_bodies"),
|
||||
("FusionCreateNewComponentCommand", "component.create"),
|
||||
("SnapshotCmd", "component.capture_position"),
|
||||
("FusionShowDesignConfigPanelCmd", "config.table"),
|
||||
("FusionStartDesignConfigModeCmd", "config.configure"),
|
||||
("FusionComputeAllCommand", "timeline.compute_all"),
|
||||
("FusionDeleteCommand", "timeline.delete"),
|
||||
("FusionRenameTimelineEntryCommand", "timeline.rename"),
|
||||
("RedoCommand", "edit.redo"),
|
||||
("UndoCommand", "edit.undo"),
|
||||
("timeline.rollTo", "timeline.roll_to"),
|
||||
("AlignCmd", "solid.align"),
|
||||
("EmbossCmd", "solid.emboss"),
|
||||
("FusionReplaceFaceCommand", "solid.replace_face"),
|
||||
("FusionRibCommand", "solid.rib"),
|
||||
("FusionWebCommand", "solid.web"),
|
||||
("PrimitiveCoil", "solid.coil"),
|
||||
("SoftDeleteCommand", "solid.remove"),
|
||||
("ConstructionPlaneAtAngleCommand", "construct.plane.at_angle"),
|
||||
("ConstructionPlaneOffsetFromPlaneCommand", "construct.plane.offset"),
|
||||
("Extrude", "solid.extrude"),
|
||||
("FusionChamferCommand", "solid.chamfer"),
|
||||
("FusionCombineCommand", "solid.combine"),
|
||||
("FusionDraftCommand", "solid.draft"),
|
||||
("FusionFilletEdgesCommand", "solid.fillet"),
|
||||
("FusionHoleCommand", "solid.hole"),
|
||||
("FusionMoveCommand", "solid.move"),
|
||||
("FusionOffsetFacesCommand", "solid.offset_face"),
|
||||
("FusionPressPullCommand", "solid.press_pull"),
|
||||
("FusionShellBodyCommand", "solid.shell"),
|
||||
("FusionSplitBodyCommand", "solid.split_body"),
|
||||
("FusionThreadCommand", "solid.thread"),
|
||||
("MirrorCommand", "solid.mirror"),
|
||||
("ModifyScale", "solid.scale"),
|
||||
("PatternCircular", "solid.pattern.circular"),
|
||||
("PatternOnPath", "solid.pattern.path"),
|
||||
("PatternRectangular", "solid.pattern.rectangular"),
|
||||
("PrimitiveBox", "solid.box"),
|
||||
("PrimitiveCylinder", "solid.cylinder"),
|
||||
("PrimitivePipe", "solid.pipe"),
|
||||
("PrimitiveSphere", "solid.sphere"),
|
||||
("PrimitiveTorus", "solid.torus"),
|
||||
("Revolve", "solid.revolve"),
|
||||
("SolidLoft", "solid.loft"),
|
||||
("StockModelCommand", "solid.bounding_solid"),
|
||||
("Sweep", "solid.sweep"),
|
||||
("ExportCommand", "file.export"),
|
||||
("FusionImportCommandFromToolbar", "file.insert_step"),
|
||||
("FusionSaveAsSTLCommand", "file.save_mesh"),
|
||||
("NewDocumentCommand", "file.new"),
|
||||
("ParaMeshInsertAlignCommand", "file.insert_mesh"),
|
||||
("SaveDocumentAsCommand", "file.save_as"),
|
||||
("SaveDocumentCommand", "file.save"),
|
||||
("AppearanceCommand", "appearance.assign"),
|
||||
("MeasureCommand", "inspect.measure"),
|
||||
("PhysicalMaterialCommand", "material.assign"),
|
||||
("FusionMotionRelationshipCommand", "joint.motion_link"),
|
||||
("FusionMoveJointsCommand", "joint.drive"),
|
||||
("InterferenceCheckCommand", "inspect.interference"),
|
||||
("JointAsBuiltCmd", "joint.as_built"),
|
||||
("JointAssembleCmdNew", "joint.create"),
|
||||
("JointOrigin", "joint.origin"),
|
||||
("RigidGroupCmd", "joint.rigid_group"),
|
||||
("ContactSetCmd", "contact.create"),
|
||||
("DisableAllContactCmd", "contact.disable_all"),
|
||||
("EnableAllContactCmd", "contact.enable_all"),
|
||||
("EnableContactSetsCmd", "contact.enable_sets"),
|
||||
("FusionMotionStudyCommand", "motion.study"),
|
||||
("ChangeParameterCommand", "parameters.change"),
|
||||
("FusionFastenersCommand", "parts.fastener"),
|
||||
("FusionAssignPlasticRuleCommand", "plastic.assign_rule"),
|
||||
("FusionBossCommand", "plastic.boss"),
|
||||
("FusionLipCommand", "plastic.lip"),
|
||||
("FusionManagePlasticRuleCommand", "plastic.manage_rules"),
|
||||
("FusionRestCommand", "plastic.rest"),
|
||||
("FusionSnapFitCommand", "plastic.snap_fit"),
|
||||
("FusionHalfSectionViewCommand", "inspect.section"),
|
||||
("ConvertToSheetMetalCmd", "sheet.convert"),
|
||||
("FusionSheetMetalFlangeCommand", "sheet.flange"),
|
||||
("FusionSheetMetalFlatPatternCmd", "sheet.flat_pattern"),
|
||||
("FusionSheetMetalHemFlangeCommand", "sheet.hem"),
|
||||
("FusionSheetMetalRulesCommand", "sheet.manage_rules"),
|
||||
("FusionSheetmetalUnfoldCommand", "sheet.unfold"),
|
||||
("SheetMetalFoldCmd", "sheet.fold"),
|
||||
("FusionAddCanvasCommand", "canvas.insert"),
|
||||
("FusionAddEditDecalCommand", "canvas.decal"),
|
||||
("ConstraintSmooth", "sketch.constraint.curvature"),
|
||||
("SketchAutoConstrainAndFinish", "sketch.finish_auto_constrain"),
|
||||
("SketchAutoConstraintAndDimCmd", "sketch.auto_constrain"),
|
||||
("SketchAutoConstraintAndDimFromDatumCmd", "sketch.auto_constrain_from_datum"),
|
||||
("SketchConstrainer", "sketch.constrainer"),
|
||||
("SketchPolygonConstraintCmd", "sketch.constraint.polygon"),
|
||||
("ArcTangent", "sketch.arc.tangent"),
|
||||
("BlendG1CurveSketchCmd", "sketch.blend_curve"),
|
||||
("CircleElipse", "sketch.ellipse"),
|
||||
("CircleTanTanRadius", "sketch.circle.two_tangent"),
|
||||
("CircleThreeTangent", "sketch.circle.three_tangent"),
|
||||
("ConicCurveCmd", "sketch.conic"),
|
||||
("DrawCVMSpline3D", "sketch.spline.control_point"),
|
||||
("DrawCVMSpline5D", "sketch.spline.control_point_5"),
|
||||
("DrawSpline", "sketch.spline.fit_point"),
|
||||
("MTextCmd", "sketch.text"),
|
||||
("ShapeArcSlotCenterTwoPoint", "sketch.slot.arc_center"),
|
||||
("ShapeArcSlotThreePoint", "sketch.slot.arc_three_point"),
|
||||
("ShapeSlotCenterPoint", "sketch.slot.center_point"),
|
||||
("SketchMidpointLine", "sketch.line.midpoint"),
|
||||
("ImportDxfFileCommand", "sketch.insert_dxf"),
|
||||
("SketchImportSVG", "sketch.insert_svg"),
|
||||
("FusionCenterOfMassCommand", "inspect.center_of_mass"),
|
||||
("FusionCurvatureCombAnalysisCommand", "inspect.curvature_comb"),
|
||||
("FusionIsoCurveAnalysisCommand", "inspect.isocurve"),
|
||||
("FusionMinimumRadiusAnalysisCommand", "inspect.minimum_radius"),
|
||||
("BreakSketchCmd", "sketch.break"),
|
||||
("ChamferSketchDistanceAngle", "sketch.chamfer.distance_angle"),
|
||||
("ChamferSketchDistanceDistance", "sketch.chamfer.two_distance"),
|
||||
("ChamferSketchEqualDistance", "sketch.chamfer.equal_distance"),
|
||||
("CircularSketchPatternCommand", "sketch.pattern.circular"),
|
||||
("ExtendSketchCmd", "sketch.extend"),
|
||||
("FilletSketchCmd", "sketch.fillet"),
|
||||
("MirrorSketchCommand", "sketch.mirror"),
|
||||
("Offset", "sketch.offset"),
|
||||
("RectangularSketchPatternCommand", "sketch.pattern.rectangular"),
|
||||
("SketchScaleCmd", "sketch.scale"),
|
||||
("TrimSketchCmd", "sketch.trim"),
|
||||
("FitCurvesToSectionCommand", "sketch.fit_curves_to_section"),
|
||||
("Include3DGeometry", "sketch.include_3d"),
|
||||
("IntersectCmd", "sketch.intersect"),
|
||||
("IntersectionCurve", "sketch.intersection_curve"),
|
||||
("ProjectNewCmd", "sketch.project"),
|
||||
("ProjectToSurface", "sketch.project_to_surface"),
|
||||
("SketchIsoparametricCurve", "sketch.isoparametric_curve"),
|
||||
("SpunProfileCmd", "sketch.spun_profile"),
|
||||
("ArcCenterTwoPoint", "sketch.arc.center_point"),
|
||||
("ArcThreePoint", "sketch.arc.three_point"),
|
||||
("CircleCenterRadius", "sketch.circle.center"),
|
||||
("CircleThreePoint", "sketch.circle.three_point"),
|
||||
("CircleTwoPoint", "sketch.circle.two_point"),
|
||||
("ConstraintCoincident", "sketch.constraint.coincident"),
|
||||
("ConstraintCollinear", "sketch.constraint.collinear"),
|
||||
("ConstraintConcentric", "sketch.constraint.concentric"),
|
||||
("ConstraintEqual", "sketch.constraint.equal"),
|
||||
("ConstraintFix", "sketch.constraint.fix"),
|
||||
("ConstraintHorizontalVertical", "sketch.constraint.horizontal_vertical"),
|
||||
("ConstraintMidPoint", "sketch.constraint.midpoint"),
|
||||
("ConstraintParallel", "sketch.constraint.parallel"),
|
||||
("ConstraintPerpendicular", "sketch.constraint.perpendicular"),
|
||||
("ConstraintSymmetry", "sketch.constraint.symmetry"),
|
||||
("ConstraintTangent", "sketch.constraint.tangent"),
|
||||
("DrawPoint", "sketch.point"),
|
||||
("DrawPolyline", "sketch.line"),
|
||||
("ShapePolygonCircumscribed", "sketch.polygon.circumscribed"),
|
||||
("ShapePolygonEdge", "sketch.polygon.edge"),
|
||||
("ShapePolygonInscribed", "sketch.polygon.inscribed"),
|
||||
("ShapeRectangleCenter", "sketch.rectangle.center"),
|
||||
("ShapeRectangleThreePoint", "sketch.rectangle.three_point"),
|
||||
("ShapeRectangleTwoPoint", "sketch.rectangle.two_point"),
|
||||
("ShapeSlotCenterToCenter", "sketch.slot.center_to_center"),
|
||||
("ShapeSlotOverall", "sketch.slot.overall"),
|
||||
("SketchActivate", "sketch.edit"),
|
||||
("SketchCreate", "sketch.create"),
|
||||
("SketchDimension", "sketch.dimension"),
|
||||
("SketchStop", "sketch.finish"),
|
||||
("FusionAccessibilityAnalysisCommand", "inspect.accessibility"),
|
||||
("FusionCurvatureMapAnalysisCommand", "inspect.curvature_map"),
|
||||
("FusionDraftAnalysisCommand", "inspect.draft"),
|
||||
("FusionEnvironmentMapAnalysisCommand", "inspect.environment_map"),
|
||||
("FusionZebraAnalysisCommand", "inspect.zebra"),
|
||||
("FusionExtendCommand", "surface.extend"),
|
||||
("FusionSurfacePatchCommand", "surface.patch"),
|
||||
("FusionSurfaceStitchCommand", "surface.stitch"),
|
||||
("FusionSurfaceThickenCommand", "surface.thicken"),
|
||||
("FusionSurfaceTrimCommand", "surface.trim"),
|
||||
("FusionSplitFaceCommand", "solid.split_face"),
|
||||
("ConstructionAxisThroughCylinderCommand", "construct.axis.through_cylinder"),
|
||||
("ConstructionAxisNormalToFaceCommand", "construct.axis.normal_to_face"),
|
||||
("ConstructionAxisFromTwoPlanesCommand", "construct.axis.two_planes"),
|
||||
("ConstructionAxisThroughTwoPointsCommand", "construct.axis.two_points"),
|
||||
("ConstructionAxisThroughEdgeCommand", "construct.axis.edge"),
|
||||
("ConstructionPointFromPointCommand", "construct.point.vertex"),
|
||||
("ConstructionPointThroughTwoEdgesCommand", "construct.point.two_edges"),
|
||||
("ConstructionPointFromThreePlanesCommand", "construct.point.three_planes"),
|
||||
("ConstructionPointFromCircleOrSphereCommand", "construct.point.center"),
|
||||
("ConstructionPointAtEdgeAndPlaneCommand", "construct.point.edge_plane"),
|
||||
("ConstructionPointAlongPathCommand", "construct.point.along_path"),
|
||||
("ConstructionMidPlaneCommand", "construct.plane.midplane"),
|
||||
("ConstructionPlaneFromTwoEdgesCommand", "construct.plane.two_edges"),
|
||||
("ConstructionPlaneFromThreePointsCommand", "construct.plane.three_points"),
|
||||
("ConstructionTangentPlaneCommand", "construct.plane.tangent"),
|
||||
("ConstructionPlaneAlongPathCommand", "construct.plane.along_path"),
|
||||
];
|
||||
|
||||
/// The current id for a command id that may be a legacy one (unchanged otherwise).
|
||||
pub fn current_id(id: &str) -> &str {
|
||||
LEGACY_IDS.iter().find(|(old, _)| old.eq_ignore_ascii_case(id)).map(|(_, new)| *new).unwrap_or(id)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn every_legacy_id_names_a_command() {
|
||||
let unknown: Vec<&str> =
|
||||
LEGACY_IDS.iter().filter(|(_, new)| crate::find_command(new).is_none_or(|c| c.id != *new)).map(|(_, new)| *new).collect();
|
||||
// The construction set and Split Face are on a branch not yet merged when the table was made.
|
||||
let pending = ["solid.split_face"];
|
||||
let unknown: Vec<&str> = unknown
|
||||
.into_iter()
|
||||
.filter(|n| {
|
||||
!pending.contains(n)
|
||||
&& !n.starts_with("construct.axis")
|
||||
&& !n.starts_with("construct.point")
|
||||
&& ![
|
||||
"construct.plane.midplane",
|
||||
"construct.plane.two_edges",
|
||||
"construct.plane.three_points",
|
||||
"construct.plane.tangent",
|
||||
"construct.plane.along_path",
|
||||
]
|
||||
.contains(n)
|
||||
})
|
||||
.collect();
|
||||
assert!(unknown.is_empty(), "{unknown:?}");
|
||||
assert_eq!(crate::find_command("SketchCreate").map(|c| c.id), Some("sketch.create"));
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@
|
||||
pub mod cmd;
|
||||
pub mod frames;
|
||||
pub mod fuzz;
|
||||
pub mod legacy_ids;
|
||||
pub mod licences;
|
||||
pub mod occurrences;
|
||||
pub mod params;
|
||||
|
||||
@@ -512,11 +512,22 @@ fn registry_is_consistent() {
|
||||
let n = ids.len();
|
||||
ids.dedup();
|
||||
assert_eq!(ids.len(), n, "duplicate command ids");
|
||||
assert!(find_command("extrude").is_some(), "case-insensitive lookup");
|
||||
assert_eq!(find_command("Solid.Extrude").map(|c| c.id), Some("solid.extrude"), "case-insensitive lookup");
|
||||
let s = Session::default();
|
||||
assert!(!find_command("sketch.line").unwrap().info(&s).enabled);
|
||||
}
|
||||
|
||||
/// Only SolidCraft's own dotted ids name commands; other ids are unknown commands.
|
||||
#[test]
|
||||
fn only_own_ids_name_commands() {
|
||||
for old in ["Extrude", "SketchCreate", "FusionFilletEdgesCommand"] {
|
||||
assert!(find_command(old).is_none(), "{old}");
|
||||
let mut s = Session::default();
|
||||
let err = s.execute(old, &serde_json::json!({})).unwrap_err();
|
||||
assert!(matches!(err, crate::EngineError::UnknownCommand(_)), "{old}: {err}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sample_design_builds() {
|
||||
let mut s = Session::default();
|
||||
@@ -2336,15 +2347,15 @@ fn boundary_fill_cells() {
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "solid.box", json!({"length": 20, "width": 20, "height": 20, "body_name": "A"}));
|
||||
run(&mut s, "solid.box", json!({"corner": [10, 0, 0], "length": 20, "width": 20, "height": 20, "body_name": "B"}));
|
||||
let r = run(&mut s, "SurfaceSculpt", json!({"tools": ["A", "B"], "cells": [[15, 10, 10]], "remove_tools": true}));
|
||||
let r = run(&mut s, "solid.boundary_fill", json!({"tools": ["A", "B"], "cells": [[15, 10, 10]], "remove_tools": true}));
|
||||
let m = run(&mut s, "inspect.measure", json!({}));
|
||||
assert_eq!(m["body_count"], 1, "{r} {m}");
|
||||
assert!(rel(m["total"]["volume_mm3"].as_f64().unwrap_or(0.0), 10.0 * 20.0 * 20.0) < 1e-9);
|
||||
run(&mut s, "edit.undo", json!({}));
|
||||
run(&mut s, "SurfaceSculpt", json!({"tools": ["A", "B"], "cells": [[5, 10, 10], [25, 10, 10]], "remove_tools": true}));
|
||||
run(&mut s, "solid.boundary_fill", json!({"tools": ["A", "B"], "cells": [[5, 10, 10], [25, 10, 10]], "remove_tools": true}));
|
||||
let m = run(&mut s, "inspect.measure", json!({}));
|
||||
assert!(rel(m["total"]["volume_mm3"].as_f64().unwrap_or(0.0), 2.0 * 10.0 * 20.0 * 20.0) < 1e-9, "{m}");
|
||||
assert!(s.execute("SurfaceSculpt", &json!({"tools": ["A"], "cells": [[100, 100, 100]]})).is_err());
|
||||
assert!(s.execute("solid.boundary_fill", &json!({"tools": ["A"], "cells": [[100, 100, 100]]})).is_err());
|
||||
}
|
||||
|
||||
/// Rectangles name their sides and corners, so they can be dimensioned without inspecting the
|
||||
|
||||
@@ -366,7 +366,7 @@ impl Dialog {
|
||||
Kind::ReplaceFace,
|
||||
vec![SelInput::new("Faces", PLANAR_FACES, true), SelInput::new("Target", PLANES | PLANAR_FACES, false)],
|
||||
),
|
||||
"SurfaceSculpt" => {
|
||||
"solid.boundary_fill" => {
|
||||
Dialog::new(Kind::BoundaryFill { operation: 0, cells: Vec::new(), of: Vec::new() }, vec![SelInput::new("Tools", BODIES, true)])
|
||||
}
|
||||
"solid.align" => Dialog::new(
|
||||
@@ -2848,7 +2848,7 @@ fn dialog_commands(app: &SolveApp, d: &Dialog) -> Result<Vec<(String, Value)>, S
|
||||
if picked.is_empty() {
|
||||
return Err("tick the cells to fill".into());
|
||||
}
|
||||
("SurfaceSculpt", json!({"tools": body_names(0), "cells": picked, "operation": OPS.get(*operation).copied().unwrap_or("new")}))
|
||||
("solid.boundary_fill", json!({"tools": body_names(0), "cells": picked, "operation": OPS.get(*operation).copied().unwrap_or("new")}))
|
||||
}
|
||||
Kind::Combine { operation, keep_tools } => {
|
||||
need(0, "the target body")?;
|
||||
@@ -3383,7 +3383,7 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
d
|
||||
}
|
||||
FeatureKind::BoundaryFill { tools, cells, operation, remove_tools } => {
|
||||
let mut d = start("SurfaceSculpt")?;
|
||||
let mut d = start("solid.boundary_fill")?;
|
||||
// The cells again, ticked where a stored cell point lies in the same cell.
|
||||
let before = s.model.state_before(f.id);
|
||||
let found = fill_cells(&before, tools);
|
||||
|
||||
@@ -38,15 +38,10 @@ impl Keymap {
|
||||
}
|
||||
pub fn load(&mut self, v: &Value) {
|
||||
self.custom =
|
||||
v.as_object().map(|o| o.iter().take(2000).filter_map(|(k, v)| Some((current(k), v.as_str()?.to_string()))).collect()).unwrap_or_default();
|
||||
v.as_object().map(|o| o.iter().take(2000).filter_map(|(k, v)| Some((k.clone(), v.as_str()?.to_string()))).collect()).unwrap_or_default();
|
||||
}
|
||||
}
|
||||
|
||||
/// Saved before the command ids were renamed: the current id.
|
||||
fn current(id: &str) -> String {
|
||||
solvecraft_engine::legacy_ids::current_id(id).to_string()
|
||||
}
|
||||
|
||||
/// A key press as a shortcut name: `E`, `Shift+E`, `Ctrl+Alt+K`, `F5`, `Delete`.
|
||||
pub fn key_name(key: egui::Key, mods: egui::Modifiers) -> String {
|
||||
let mut s = String::new();
|
||||
|
||||
@@ -594,8 +594,8 @@ fn toolbar_pins_removes_reorders_and_keeps_its_layout() {
|
||||
tc::reorder(&mut app, "SOLID", extra, "MODIFY", None);
|
||||
assert!(!ids(&app, "CREATE").contains(&extra) && ids(&app, "MODIFY").last() == Some(&extra));
|
||||
// Pin to Shortcuts goes to the S box's favourites.
|
||||
act(&mut app, &Target::ToolbarCommand { id: "Extrude".into() }, "Pin to Shortcuts");
|
||||
assert!(app.sbox.pinned.iter().any(|p| p == "Extrude"));
|
||||
act(&mut app, &Target::ToolbarCommand { id: "solid.extrude".into() }, "Pin to Shortcuts");
|
||||
assert!(app.sbox.pinned.iter().any(|p| p == "solid.extrude"));
|
||||
// Kept between runs, and exported and imported with the shortcuts.
|
||||
let mut other = sample_app();
|
||||
other.load_prefs(&app.prefs());
|
||||
|
||||
@@ -543,7 +543,7 @@ fn boundary_fill_finds_the_cells_and_fills_the_ticked_ones() {
|
||||
{"command": "solid.box", "params": {"length": 20, "width": 20, "height": 20}},
|
||||
{"command": "solid.box", "params": {"length": 20, "width": 20, "height": 20, "corner": [10, 10, 0], "operation": "new"}}
|
||||
]));
|
||||
let mut d = start(&mut app, vec![], "SurfaceSculpt");
|
||||
let mut d = start(&mut app, vec![], "solid.boundary_fill");
|
||||
d.inputs[0].items = vec![Sel::Body { name: "Body1".into() }, Sel::Body { name: "Body2".into() }];
|
||||
app.dialog = Some(d);
|
||||
// The dialog finds the cells on its next frame.
|
||||
|
||||
@@ -34,10 +34,7 @@ impl ShortcutBox {
|
||||
}
|
||||
pub fn load(&mut self, v: &Value) {
|
||||
let list = |k: &str| -> Vec<String> {
|
||||
v.get(k)
|
||||
.and_then(Value::as_array)
|
||||
.map(|a| a.iter().take(64).filter_map(|x| x.as_str().map(|id| solvecraft_engine::legacy_ids::current_id(id).to_string())).collect())
|
||||
.unwrap_or_default()
|
||||
v.get(k).and_then(Value::as_array).map(|a| a.iter().take(64).filter_map(|x| x.as_str().map(str::to_string)).collect()).unwrap_or_default()
|
||||
};
|
||||
self.recent = list("recent");
|
||||
self.pinned = list("pinned");
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
- [Test harnesses](dev/testing.md)
|
||||
- [Control protocol](dev/control-protocol.md)
|
||||
- [Reference tests](dev/oracle.md)
|
||||
- [Command parity](dev/parity.md)
|
||||
- [Features](dev/features.md)
|
||||
- [STEP import](dev/step-import.md)
|
||||
|
||||
# Reference
|
||||
|
||||
@@ -7,7 +7,7 @@ SolidCraft is a Cargo workspace in layers. A crate only depends on crates in low
|
||||
|
||||
The web app, `apps/solvecraft-web`, is the desktop front end compiled to wasm with
|
||||
[trunk](https://trunkrs.dev). `xtask` holds the repository's own tooling: `cargo xtask ci`,
|
||||
`layers`, `assets`, `oracle`, `parity` and `book`.
|
||||
`layers`, `assets`, `features`, `oracle` and `book`.
|
||||
|
||||
A few rules follow from the layering:
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ before it runs, and a failing command leaves the document unchanged. Feature com
|
||||
feature to the timeline and let the document evaluate it; they validate their inputs first
|
||||
(units, ranges, references) and return `BadParams` instead of building a broken feature.
|
||||
|
||||
Ids used before the 2026-10 rename still resolve through `crates/engine/src/legacy_ids.rs`, so
|
||||
old scripts, recipes, saved shortcuts and toolbar layouts keep working.
|
||||
Only the registry's own dotted ids name commands (matched ignoring case); any other id fails
|
||||
with `unknown command`.
|
||||
|
||||
## Adding a command
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{{#include ../../../features.md}}
|
||||
@@ -1 +0,0 @@
|
||||
{{#include ../../../parity.md}}
|
||||
@@ -10,4 +10,4 @@ The PLASTIC tab has a small enclosure subset:
|
||||
clearance per material, used as the features' defaults.
|
||||
|
||||
Rib and web (on the SOLID tab) complete the set. These features are checked against
|
||||
hand-computed geometry rather than a Fusion oracle.
|
||||
hand-computed geometry.
|
||||
@@ -11,8 +11,8 @@ The SHEET METAL tab builds parts from a sheet of constant thickness under a **sh
|
||||
- **Create Flat Pattern** (`sheet.flat_pattern`) shows the flat part with its bend lines and a
|
||||
bend table, and exports it as DXF or a bend-table CSV through the save picker.
|
||||
|
||||
Bends follow the rule's K-factor, so flat lengths match what a press brake will make. The
|
||||
oracle checks these against parts built in Fusion.
|
||||
Bends follow the rule's K-factor, so flat lengths match what a press brake will make. Tests
|
||||
check flat lengths against hand-computed bend allowances.
|
||||
|
||||
For a shop drawing or spreadsheet, `sheet.export_bend_table` returns CSV by default; choose
|
||||
`format: "json"` for structured data. It includes the sheet rule, thickness, bend angles,
|
||||
|
||||
@@ -21,8 +21,8 @@ also script, test or hand to an agent.
|
||||
SolidCraft is early. Sketching, solid modelling, parameters, components with joints, sheet metal
|
||||
and a plastic-enclosure subset work; surfaces, drawings, CAM and simulation are deferred. The
|
||||
[roadmap](https://github.com/bherbruck/solidcraft/blob/main/ROADMAP.md) has the details, and
|
||||
[command parity](dev/parity.md) and the [reference tests](dev/oracle.md) measure how far along it
|
||||
is.
|
||||
the [feature list](dev/features.md) lists every command by area, and the
|
||||
[reference tests](dev/oracle.md) check modelling results against analytic and FreeCAD values.
|
||||
|
||||
Existing `.solvecraft` designs and `solvecraft-cli` commands keep their names and behavior.
|
||||
|
||||
@@ -30,5 +30,7 @@ This book has two halves: the **user guide** for people modelling with SolidCraf
|
||||
**developer guide** for people working on it. The [command reference](reference/commands.md) is
|
||||
generated from the code on every build.
|
||||
|
||||
SolidCraft is licensed MIT OR Apache-2.0. It is a clean-room implementation and is not affiliated
|
||||
with Autodesk; Fusion is a trademark of Autodesk, Inc.
|
||||
SolidCraft is licensed MIT OR Apache-2.0. It is independent: behaviour is designed from public
|
||||
documentation, general CAD conventions and user feedback, and reference tests use analytic
|
||||
values and open-source tools. SolidCraft is not affiliated with Autodesk; Fusion is a trademark
|
||||
of Autodesk, Inc.
|
||||
@@ -0,0 +1,487 @@
|
||||
# Features
|
||||
|
||||
SolidCraft's commands by area, generated by `cargo xtask features` from the command registry (`solvecraft-cli commands`). **314 commands.** Every command runs the same way from the toolbar, a script, `solvecraft-cli exec <id> '<json>'`, the control channel and MCP; parameters are in the [command reference](book/src/reference/commands.md) (`cargo xtask book`). Status and plans: [ROADMAP](../ROADMAP.md).
|
||||
|
||||
## Sketch (97)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Create Sketch | `sketch.create` | SOLID › CREATE |
|
||||
| Edit Sketch | `sketch.edit` | – |
|
||||
| Finish Sketch | `sketch.finish` | SKETCH › FINISH SKETCH |
|
||||
| Line (L) | `sketch.line` | SKETCH › CREATE |
|
||||
| Draw Dimensioned Sketch Geometry | `sketch.draw.dimensioned` | – |
|
||||
| 2-Point Rectangle (R) | `sketch.rectangle.two_point` | SKETCH › CREATE |
|
||||
| 3-Point Rectangle | `sketch.rectangle.three_point` | SKETCH › CREATE |
|
||||
| Center Rectangle | `sketch.rectangle.center` | SKETCH › CREATE |
|
||||
| Center Diameter Circle (C) | `sketch.circle.center` | SKETCH › CREATE |
|
||||
| 2-Point Circle | `sketch.circle.two_point` | SKETCH › CREATE |
|
||||
| 3-Point Circle | `sketch.circle.three_point` | SKETCH › CREATE |
|
||||
| 3-Point Arc | `sketch.arc.three_point` | SKETCH › CREATE |
|
||||
| Center Point Arc | `sketch.arc.center_point` | SKETCH › CREATE |
|
||||
| Inscribed Polygon | `sketch.polygon.inscribed` | SKETCH › CREATE |
|
||||
| Circumscribed Polygon | `sketch.polygon.circumscribed` | SKETCH › CREATE |
|
||||
| Edge Polygon | `sketch.polygon.edge` | SKETCH › CREATE |
|
||||
| Center to Center Slot | `sketch.slot.center_to_center` | SKETCH › CREATE |
|
||||
| Overall Slot | `sketch.slot.overall` | SKETCH › CREATE |
|
||||
| Point | `sketch.point` | SKETCH › CREATE |
|
||||
| Sketch Dimension (D) | `sketch.dimension` | SKETCH › CREATE |
|
||||
| Horizontal/Vertical | `sketch.constraint.horizontal_vertical` | SKETCH › CONSTRAINTS |
|
||||
| Coincident | `sketch.constraint.coincident` | SKETCH › CONSTRAINTS |
|
||||
| Tangent | `sketch.constraint.tangent` | SKETCH › CONSTRAINTS |
|
||||
| Equal | `sketch.constraint.equal` | SKETCH › CONSTRAINTS |
|
||||
| Parallel | `sketch.constraint.parallel` | SKETCH › CONSTRAINTS |
|
||||
| Perpendicular | `sketch.constraint.perpendicular` | SKETCH › CONSTRAINTS |
|
||||
| Fix/UnFix | `sketch.constraint.fix` | SKETCH › CONSTRAINTS |
|
||||
| MidPoint | `sketch.constraint.midpoint` | SKETCH › CONSTRAINTS |
|
||||
| Concentric | `sketch.constraint.concentric` | SKETCH › CONSTRAINTS |
|
||||
| Collinear | `sketch.constraint.collinear` | SKETCH › CONSTRAINTS |
|
||||
| Symmetry | `sketch.constraint.symmetry` | SKETCH › CONSTRAINTS |
|
||||
| Normal/Construction (X) | `sketch.construction` | SKETCH › CREATE |
|
||||
| Delete Sketch Entities | `sketch.delete` | – |
|
||||
| Drag Sketch Point | `sketch.move_point` | – |
|
||||
| Drag Sketch Geometry | `sketch.drag` | – |
|
||||
| Move Dimension Text | `sketch.dimension_text` | – |
|
||||
| Sketch Palette Options | `sketch.options` | – |
|
||||
| Chain | `sketch.chain` | – |
|
||||
| Solve Sketch | `sketch.solve` | – |
|
||||
| Midpoint Line | `sketch.line.midpoint` | SKETCH › CREATE |
|
||||
| Tangent Arc | `sketch.arc.tangent` | SKETCH › CREATE |
|
||||
| 2-Tangent Circle | `sketch.circle.two_tangent` | SKETCH › CREATE |
|
||||
| 3-Tangent Circle | `sketch.circle.three_tangent` | SKETCH › CREATE |
|
||||
| Center Point Slot | `sketch.slot.center_point` | SKETCH › CREATE |
|
||||
| Three Point Arc Slot | `sketch.slot.arc_three_point` | SKETCH › CREATE |
|
||||
| Center Point Arc Slot | `sketch.slot.arc_center` | SKETCH › CREATE |
|
||||
| Ellipse | `sketch.ellipse` | SKETCH › CREATE |
|
||||
| Fit Point Spline | `sketch.spline.fit_point` | SKETCH › CREATE |
|
||||
| Control Point Spline | `sketch.spline.control_point` | SKETCH › CREATE |
|
||||
| Control Point Spline (Degree 5) | `sketch.spline.control_point_5` | SKETCH › CREATE |
|
||||
| Conic Curve | `sketch.conic` | SKETCH › CREATE |
|
||||
| Blend Curve | `sketch.blend_curve` | SKETCH › MODIFY |
|
||||
| Centerline | `sketch.centerline` | – |
|
||||
| Text | `sketch.text` | SKETCH › CREATE |
|
||||
| Edit Text | `sketch.edit_text` | – |
|
||||
| Curvature | `sketch.constraint.curvature` | SKETCH › CONSTRAINTS |
|
||||
| Polygon | `sketch.constraint.polygon` | SKETCH › CONSTRAINTS |
|
||||
| AutoConstrain | `sketch.auto_constrain` | SKETCH › CONSTRAINTS |
|
||||
| AutoConstrain from datum | `sketch.auto_constrain_from_datum` | SKETCH › CONSTRAINTS |
|
||||
| Finish with AutoConstrain | `sketch.finish_auto_constrain` | SKETCH › FINISH SKETCH |
|
||||
| Sketch Constrainer | `sketch.constrainer` | SKETCH › CREATE |
|
||||
| Toggle Driven Dimension | `sketch.toggle_driven` | – |
|
||||
| Constraint Glyphs | `sketch.glyphs` | – |
|
||||
| Snap Inference | `sketch.snap` | – |
|
||||
| Insert DXF | `sketch.insert_dxf` | SKETCH › INSERT |
|
||||
| Insert SVG | `sketch.insert_svg` | SKETCH › INSERT |
|
||||
| Save As DXF | `sketch.export_dxf` | – |
|
||||
| 3D Line | `sketch.line3d` | – |
|
||||
| 3D Spline | `sketch.spline3d` | – |
|
||||
| 3D Point | `sketch.point3d` | – |
|
||||
| Move 3D Point | `sketch.move3d` | – |
|
||||
| Fillet | `sketch.fillet` | SKETCH › MODIFY |
|
||||
| Equal Distance Chamfer | `sketch.chamfer.equal_distance` | SKETCH › MODIFY |
|
||||
| Distance and Angle Chamfer | `sketch.chamfer.distance_angle` | SKETCH › MODIFY |
|
||||
| Two Distance Chamfer | `sketch.chamfer.two_distance` | SKETCH › MODIFY |
|
||||
| Offset (O) | `sketch.offset` | SKETCH › MODIFY |
|
||||
| Break Offset Association | `sketch.offset.break` | – |
|
||||
| Trim (T) | `sketch.trim` | SKETCH › MODIFY |
|
||||
| Extend | `sketch.extend` | SKETCH › MODIFY |
|
||||
| Break | `sketch.break` | SKETCH › MODIFY |
|
||||
| Sketch Scale | `sketch.scale` | SKETCH › MODIFY |
|
||||
| Move/Copy Sketch Entities | `sketch.move` | – |
|
||||
| Mirror | `sketch.mirror` | SKETCH › CREATE |
|
||||
| Circular Pattern | `sketch.pattern.circular` | SKETCH › CREATE |
|
||||
| Rectangular Pattern | `sketch.pattern.rectangular` | SKETCH › CREATE |
|
||||
| Project (P) | `sketch.project` | SKETCH › CREATE |
|
||||
| Intersect | `sketch.intersect` | SKETCH › CREATE |
|
||||
| Include 3D Geometry | `sketch.include_3d` | SKETCH › CREATE |
|
||||
| Project To Surface | `sketch.project_to_surface` | SKETCH › CREATE |
|
||||
| Intersection Curve | `sketch.intersection_curve` | SKETCH › CREATE |
|
||||
| Spun Profile | `sketch.spun_profile` | SKETCH › CREATE |
|
||||
| Isoparametric Curve | `sketch.isoparametric_curve` | SKETCH › CREATE |
|
||||
| Fit Curves to Mesh Section | `sketch.fit_curves_to_section` | SKETCH › CREATE |
|
||||
| Break Link | `sketch.break_link` | – |
|
||||
| Auto-Project Edges on Reference | `sketch.auto_project` | – |
|
||||
| Redefine Sketch Plane | `sketch.redefine` | – |
|
||||
| Inspect Sketch | `sketch.inspect` | – |
|
||||
|
||||
## Solid modelling (35)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Extrude (E) | `solid.extrude` | SOLID › CREATE |
|
||||
| Revolve | `solid.revolve` | SOLID › CREATE |
|
||||
| Sweep | `solid.sweep` | SOLID › CREATE |
|
||||
| Loft | `solid.loft` | SOLID › CREATE |
|
||||
| Box | `solid.box` | SOLID › CREATE |
|
||||
| Cylinder | `solid.cylinder` | SOLID › CREATE |
|
||||
| Sphere | `solid.sphere` | SOLID › CREATE |
|
||||
| Torus | `solid.torus` | SOLID › CREATE |
|
||||
| Fillet (F) | `solid.fillet` | SOLID › MODIFY |
|
||||
| Chamfer | `solid.chamfer` | SOLID › MODIFY |
|
||||
| Combine | `solid.combine` | SOLID › MODIFY |
|
||||
| Rectangular Pattern | `solid.pattern.rectangular` | SOLID › CREATE |
|
||||
| Circular Pattern | `solid.pattern.circular` | SOLID › CREATE |
|
||||
| Pattern on Path | `solid.pattern.path` | SOLID › CREATE |
|
||||
| Mirror | `solid.mirror` | SOLID › CREATE |
|
||||
| Hole (H) | `solid.hole` | SOLID › CREATE |
|
||||
| Pipe | `solid.pipe` | SOLID › CREATE |
|
||||
| Bounding Solid | `solid.bounding_solid` | SOLID › CREATE |
|
||||
| Scale | `solid.scale` | SOLID › MODIFY |
|
||||
| Offset Face | `solid.offset_face` | SOLID › MODIFY |
|
||||
| Thread | `solid.thread` | SOLID › CREATE |
|
||||
| Shell | `solid.shell` | SOLID › MODIFY |
|
||||
| Draft | `solid.draft` | SOLID › MODIFY |
|
||||
| Split Face | `solid.split_face` | SOLID › MODIFY |
|
||||
| Split Body | `solid.split_body` | SOLID › MODIFY |
|
||||
| Press Pull (Q) | `solid.press_pull` | SOLID › MODIFY |
|
||||
| Move/Copy (M) | `solid.move` | SOLID › MODIFY |
|
||||
| Boundary Fill | `solid.boundary_fill` | SOLID › CREATE |
|
||||
| Coil | `solid.coil` | SOLID › CREATE |
|
||||
| Rib | `solid.rib` | SOLID › CREATE |
|
||||
| Web | `solid.web` | SOLID › CREATE |
|
||||
| Emboss | `solid.emboss` | SOLID › CREATE |
|
||||
| Replace Face | `solid.replace_face` | SOLID › MODIFY |
|
||||
| Align | `solid.align` | SOLID › MODIFY |
|
||||
| Remove | `solid.remove` | SOLID › MODIFY |
|
||||
|
||||
## Surfaces (5)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Patch | `surface.patch` | SURFACE › CREATE |
|
||||
| Stitch | `surface.stitch` | SURFACE › MODIFY |
|
||||
| Thicken | `surface.thicken` | SURFACE › CREATE |
|
||||
| Extend | `surface.extend` | SURFACE › MODIFY |
|
||||
| Trim | `surface.trim` | SURFACE › MODIFY |
|
||||
|
||||
## Construction geometry (19)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Offset Plane | `construct.plane.offset` | SOLID › CONSTRUCT |
|
||||
| Plane at Angle | `construct.plane.at_angle` | SOLID › CONSTRUCT |
|
||||
| Axis Through Cylinder/Cone/Torus | `construct.axis.through_cylinder` | SOLID › CONSTRUCT |
|
||||
| Axis Perpendicular To Face | `construct.axis.normal_to_face` | SOLID › CONSTRUCT |
|
||||
| Axis Through Two Planes | `construct.axis.two_planes` | SOLID › CONSTRUCT |
|
||||
| Axis Through Two Points | `construct.axis.two_points` | SOLID › CONSTRUCT |
|
||||
| Axis Through Edge | `construct.axis.edge` | SOLID › CONSTRUCT |
|
||||
| Point At Vertex | `construct.point.vertex` | SOLID › CONSTRUCT |
|
||||
| Point Through Two Edges | `construct.point.two_edges` | SOLID › CONSTRUCT |
|
||||
| Point Through Three Planes | `construct.point.three_planes` | SOLID › CONSTRUCT |
|
||||
| Point At Center Of Circle/Sphere/Torus | `construct.point.center` | SOLID › CONSTRUCT |
|
||||
| Point At Edge And Plane | `construct.point.edge_plane` | SOLID › CONSTRUCT |
|
||||
| Point Along Path | `construct.point.along_path` | SOLID › CONSTRUCT |
|
||||
| Midplane | `construct.plane.midplane` | SOLID › CONSTRUCT |
|
||||
| Plane Through Two Edges | `construct.plane.two_edges` | SOLID › CONSTRUCT |
|
||||
| Plane Through Three Points | `construct.plane.three_points` | SOLID › CONSTRUCT |
|
||||
| Tangent Plane | `construct.plane.tangent` | SOLID › CONSTRUCT |
|
||||
| Plane Along Path | `construct.plane.along_path` | SOLID › CONSTRUCT |
|
||||
| Perpendicular Plane | `construct.plane.perpendicular` | SOLID › CONSTRUCT |
|
||||
|
||||
## Sheet metal (11)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Flange | `sheet.flange` | SHEET METAL › CREATE |
|
||||
| Hem | `sheet.hem` | SHEET METAL › CREATE |
|
||||
| Fold | `sheet.fold` | SHEET METAL › CREATE |
|
||||
| Unfold | `sheet.unfold` | SHEET METAL › MODIFY |
|
||||
| Refold | `sheet.refold` | SHEET METAL › MODIFY |
|
||||
| Convert to Sheet Metal | `sheet.convert` | SHEET METAL › CREATE |
|
||||
| Sheet Metal Rules | `sheet.manage_rules` | SHEET METAL › MODIFY |
|
||||
| List Sheet Metal Rules | `sheet.rules` | – |
|
||||
| Create Flat Pattern | `sheet.flat_pattern` | SHEET METAL › CREATE |
|
||||
| Export Flat Pattern as DXF | `sheet.export_dxf` | – |
|
||||
| Export Bend Table | `sheet.export_bend_table` | – |
|
||||
|
||||
## Plastic parts (7)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Boss | `plastic.boss` | PLASTIC › CREATE |
|
||||
| Lip | `plastic.lip` | PLASTIC › CREATE |
|
||||
| Snap Fit | `plastic.snap_fit` | PLASTIC › CREATE |
|
||||
| Rest | `plastic.rest` | PLASTIC › CREATE |
|
||||
| Manage Plastic Rules | `plastic.manage_rules` | PLASTIC › SETUP |
|
||||
| Assign Plastic Rule | `plastic.assign_rule` | PLASTIC › SETUP |
|
||||
| List Plastic Rules | `plastic.rules` | – |
|
||||
|
||||
## Components (12)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| New Component | `component.create` | SOLID › ASSEMBLE |
|
||||
| Create Components from Bodies | `component.from_bodies` | – |
|
||||
| Activate Component | `component.activate` | – |
|
||||
| List Components | `component.list` | – |
|
||||
| Component Physical Properties | `component.properties` | – |
|
||||
| Rename Component | `component.rename` | – |
|
||||
| Delete Component | `component.delete` | – |
|
||||
| Move Bodies to Component | `component.move_bodies` | – |
|
||||
| Move Sketches to Component | `component.move_sketches` | – |
|
||||
| Paste New | `component.paste_new` | – |
|
||||
| Capture Position | `component.capture_position` | SOLID › POSITION |
|
||||
| Revert Position | `component.revert_position` | SOLID › POSITION |
|
||||
|
||||
## Assembly joints (11)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Joint Origin | `joint.origin` | SOLID › CREATE |
|
||||
| Joint (J) | `joint.create` | SOLID › ASSEMBLE |
|
||||
| As-Built Joint | `joint.as_built` | SOLID › ASSEMBLE |
|
||||
| Rigid Group | `joint.rigid_group` | SOLID › ASSEMBLE |
|
||||
| Drive Joints | `joint.drive` | SOLID › ASSEMBLE |
|
||||
| Motion Link | `joint.motion_link` | SOLID › ASSEMBLE |
|
||||
| Joint Limits | `joint.limits` | – |
|
||||
| Edit Joint | `joint.edit` | – |
|
||||
| Delete Joint | `joint.delete` | – |
|
||||
| List Joints | `joint.list` | – |
|
||||
| Solve Joints | `joint.solve` | – |
|
||||
|
||||
## Configurations (8)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Configure | `config.configure` | SOLID › CONFIGURE |
|
||||
| Display Configuration Table | `config.table` | SOLID › CONFIGURE |
|
||||
| Configuration Column | `config.column` | – |
|
||||
| Configuration Row | `config.row` | – |
|
||||
| Activate Configuration | `config.activate` | – |
|
||||
| Preview Configuration | `config.preview` | – |
|
||||
| Configuration Rule | `config.rule` | – |
|
||||
| Configuration Rules | `config.rules` | – |
|
||||
|
||||
## Timeline (13)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Compute All | `timeline.compute_all` | SOLID › MODIFY |
|
||||
| Delete (Delete) | `timeline.delete` | SOLID › MODIFY |
|
||||
| Rename | `timeline.rename` | – |
|
||||
| Move Timeline Marker | `timeline.rollback` | – |
|
||||
| Roll History Marker | `timeline.roll_to` | – |
|
||||
| Reorder Feature | `timeline.reorder` | – |
|
||||
| Edit Feature | `timeline.redefine` | – |
|
||||
| Feature Dependents | `timeline.dependents` | – |
|
||||
| Suppress Feature | `timeline.suppress` | – |
|
||||
| Edit Feature | `timeline.edit` | – |
|
||||
| Inspect Feature | `timeline.inspect` | – |
|
||||
| Copy Features | `timeline.copy` | – |
|
||||
| Paste Features | `timeline.paste` | – |
|
||||
|
||||
## Inspect (12)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Curvature Comb Analysis | `inspect.curvature_comb` | SKETCH › INSPECT |
|
||||
| Minimum Radius Analysis | `inspect.minimum_radius` | SKETCH › INSPECT |
|
||||
| Isocurve Analysis | `inspect.isocurve` | SKETCH › INSPECT |
|
||||
| Center of Mass | `inspect.center_of_mass` | SKETCH › INSPECT |
|
||||
| Zebra Analysis | `inspect.zebra` | SKETCH › INSPECT |
|
||||
| Draft Analysis | `inspect.draft` | SKETCH › INSPECT |
|
||||
| Environment Map Analysis | `inspect.environment_map` | SKETCH › INSPECT |
|
||||
| Accessibility Analysis | `inspect.accessibility` | SKETCH › INSPECT |
|
||||
| Curvature Map Analysis | `inspect.curvature_map` | SKETCH › INSPECT |
|
||||
| Interference | `inspect.interference` | SOLID › INSPECT |
|
||||
| Measure (I) | `inspect.measure` | SOLID › INSPECT |
|
||||
| Section Analysis | `inspect.section` | SOLID › INSPECT |
|
||||
|
||||
## Files (7)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| New Design (Ctrl+N) | `file.new` | – |
|
||||
| Insert STEP | `file.insert_step` | SOLID › INSERT |
|
||||
| Insert Mesh | `file.insert_mesh` | SOLID › INSERT |
|
||||
| Save (Ctrl+S) | `file.save` | – |
|
||||
| Save As | `file.save_as` | – |
|
||||
| Export | `file.export` | – |
|
||||
| Save As Mesh | `file.save_mesh` | – |
|
||||
|
||||
## Documents (4)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Open (Ctrl+O) | `doc.open` | – |
|
||||
| Recoverable Designs | `doc.recovery_list` | – |
|
||||
| Recover Design | `doc.recover` | – |
|
||||
| Discard Recovered Design | `doc.recovery_discard` | – |
|
||||
|
||||
## Edit (4)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Undo (Ctrl+Z) | `edit.undo` | – |
|
||||
| Redo (Ctrl+Y) | `edit.redo` | – |
|
||||
| Checkpoint | `edit.checkpoint` | – |
|
||||
| Restore Checkpoint | `edit.restore_checkpoint` | – |
|
||||
|
||||
## `appearance.*` (3)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Appearance (A) | `appearance.assign` | SOLID › MODIFY |
|
||||
| Appearance Library | `appearance.library` | – |
|
||||
| List Appearances | `appearance.list` | – |
|
||||
|
||||
## `body.*` (1)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Rename Body | `body.rename` | – |
|
||||
|
||||
## `browser.*` (6)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| New Group | `browser.group` | – |
|
||||
| Ungroup | `browser.ungroup` | – |
|
||||
| Rename Group | `browser.rename_group` | – |
|
||||
| Move Browser Items | `browser.move` | – |
|
||||
| Order Browser Items | `browser.order` | – |
|
||||
| Show/Hide | `browser.visibility` | – |
|
||||
|
||||
## `canvas.*` (5)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Canvas | `canvas.insert` | SKETCH › INSERT |
|
||||
| Decal | `canvas.decal` | SKETCH › INSERT |
|
||||
| Edit Canvas | `canvas.edit` | SKETCH › INSERT |
|
||||
| Calibrate Canvas | `canvas.calibrate` | – |
|
||||
| Delete Canvas | `canvas.delete` | – |
|
||||
|
||||
## `contact.*` (7)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Enable Contact Sets | `contact.enable_sets` | SOLID › ASSEMBLE |
|
||||
| Enable All Contact | `contact.enable_all` | SOLID › ASSEMBLE |
|
||||
| Disable Contact | `contact.disable_all` | SOLID › ASSEMBLE |
|
||||
| New Contact Set | `contact.create` | SOLID › ASSEMBLE |
|
||||
| Edit Contact Set | `contact.edit` | – |
|
||||
| List Contact Sets | `contact.list` | – |
|
||||
| Check Contact | `contact.check` | – |
|
||||
|
||||
## `document.*` (2)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Change Design Units | `document.units` | – |
|
||||
| Inspect Design | `document.inspect` | – |
|
||||
|
||||
## `engine.*` (1)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| List Commands | `engine.commands` | – |
|
||||
|
||||
## `explode.*` (4)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Exploded View | `explode.create` | SOLID › ASSEMBLE |
|
||||
| Show Exploded View | `explode.show` | – |
|
||||
| List Exploded Views | `explode.list` | – |
|
||||
| Delete Exploded View | `explode.delete` | – |
|
||||
|
||||
## `expr.*` (1)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Evaluate Expression | `expr.evaluate` | – |
|
||||
|
||||
## `face.*` (1)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Delete Face | `face.delete` | SOLID › MODIFY |
|
||||
|
||||
## `material.*` (2)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Physical Material | `material.assign` | SOLID › MODIFY |
|
||||
| List Materials | `material.list` | – |
|
||||
|
||||
## `mesh.*` (1)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Convert Mesh | `mesh.convert` | MESH › MODIFY |
|
||||
|
||||
## `model.*` (3)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| List Edges | `model.edges` | – |
|
||||
| List Faces | `model.faces` | – |
|
||||
| List Threads | `model.threads` | – |
|
||||
|
||||
## `motion.*` (5)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Motion Study | `motion.study` | SOLID › ASSEMBLE |
|
||||
| Play Motion Study | `motion.play` | – |
|
||||
| Export Motion Study | `motion.export` | – |
|
||||
| List Motion Studies | `motion.list` | – |
|
||||
| Delete Motion Study | `motion.delete` | – |
|
||||
|
||||
## `occurrence.*` (4)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Occurrence Physical Properties | `occurrence.properties` | – |
|
||||
| Paste (Instance) | `occurrence.copy` | – |
|
||||
| Move Occurrence | `occurrence.move` | – |
|
||||
| Ground | `occurrence.ground` | – |
|
||||
|
||||
## `parameters.*` (12)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Change Parameters | `parameters.change` | SOLID › MODIFY |
|
||||
| List Parameters | `parameters.list` | – |
|
||||
| Add User Parameter | `parameters.add` | – |
|
||||
| Rename Parameter | `parameters.rename` | – |
|
||||
| Delete Parameter | `parameters.delete` | – |
|
||||
| Favourite Parameter | `parameters.favorite` | – |
|
||||
| Comment Parameter | `parameters.comment` | – |
|
||||
| Parameter Users | `parameters.users` | – |
|
||||
| Parameter Graph | `parameters.graph` | – |
|
||||
| Export Parameters | `parameters.export` | – |
|
||||
| Import Parameters | `parameters.import` | – |
|
||||
| Complete Expression | `parameters.complete` | – |
|
||||
|
||||
## `parts.*` (4)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Standard Parts | `parts.library` | – |
|
||||
| Insert Fastener | `parts.fastener` | SOLID › INSERT |
|
||||
| Insert Part | `parts.insert` | – |
|
||||
| Change Part Size | `parts.resize` | – |
|
||||
|
||||
## `select.*` (2)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Select | `select.set` | – |
|
||||
| Clear Selection | `select.clear` | – |
|
||||
|
||||
## `selection.*` (1)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| Delete | `selection.delete` | – |
|
||||
|
||||
## `view.*` (4)
|
||||
|
||||
| Command | Id | Toolbar |
|
||||
|---|---|---|
|
||||
| New Named View | `view.save` | – |
|
||||
| Rename Named View | `view.rename` | – |
|
||||
| Delete Named View | `view.delete` | – |
|
||||
| List Named Views | `view.list` | – |
|
||||
-406
@@ -1,406 +0,0 @@
|
||||
# Fusion command parity
|
||||
|
||||
Generated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the toolbar commands of Fusion's Design workspace, ids and names only) and the live command registry (`solvecraft-cli commands`). A command counts as live when SolidCraft registers the same command id. This measures breadth, not depth; see ROADMAP.md and docs/oracle.md for depth.
|
||||
|
||||
**In scope (SOLID, SKETCH, ASSEMBLY, SHEET METAL, PLASTIC enclosure subset): 335 / 541 commands live (62%).** SOLID + SKETCH: 188 / 291 (65%). Registered commands: 314.
|
||||
|
||||
Deferred until further notice (not in the in-scope figure): MESH, FORM, SURFACE beyond what solids need, PCB, render, animation, simulation, manufacture, drawings, MANAGE, UTILITIES and the rest of PLASTIC. All Design tabs together: 631 / 1175 (54%).
|
||||
|
||||
| Tab | Panel | Live | Total | % |
|
||||
|---|---|---:|---:|---:|
|
||||
| SOLID | CREATE | 23 | 35 | 66% |
|
||||
| SOLID | MODIFY | 19 | 32 | 59% |
|
||||
| SOLID | ASSEMBLE | 12 | 21 | 57% |
|
||||
| SOLID | CONFIGURE | 3 | 3 | 100% |
|
||||
| SOLID | CONSTRUCT | 19 | 20 | 95% |
|
||||
| SOLID | INSPECT | 12 | 25 | 48% |
|
||||
| SOLID | INSERT | 6 | 11 | 55% |
|
||||
| SOLID | SELECT | 0 | 15 | 0% |
|
||||
| SOLID | POSITION | 2 | 2 | 100% |
|
||||
| SKETCH | CREATE | 41 | 41 | 100% |
|
||||
| SKETCH | MODIFY | 12 | 12 | 100% |
|
||||
| SKETCH | CONSTRAINTS | 15 | 15 | 100% |
|
||||
| SKETCH | CONFIGURE | 3 | 3 | 100% |
|
||||
| SKETCH | INSPECT | 12 | 25 | 48% |
|
||||
| SKETCH | INSERT | 7 | 13 | 54% |
|
||||
| SKETCH | ASSEMBLE | 0 | 1 | 0% |
|
||||
| SKETCH | SELECT | 0 | 15 | 0% |
|
||||
| SKETCH | FINISH SKETCH | 2 | 2 | 100% |
|
||||
| SHEET METAL | CREATE | 15 | 19 | 79% |
|
||||
| SHEET METAL | MODIFY | 12 | 21 | 57% |
|
||||
| SHEET METAL | ASSEMBLE | 11 | 20 | 55% |
|
||||
| SHEET METAL | CONFIGURE | 3 | 3 | 100% |
|
||||
| SHEET METAL | CONSTRUCT | 19 | 20 | 95% |
|
||||
| SHEET METAL | INSPECT | 12 | 25 | 48% |
|
||||
| SHEET METAL | INSERT | 6 | 11 | 55% |
|
||||
| SHEET METAL | SELECT | 0 | 15 | 0% |
|
||||
| SHEET METAL | REFOLD | 0 | 1 | 0% |
|
||||
| SHEET METAL | POSITION | 2 | 2 | 100% |
|
||||
| ASSEMBLY | INSERT | 4 | 8 | 50% |
|
||||
| ASSEMBLY | CREATE | 5 | 8 | 62% |
|
||||
| ASSEMBLY | RELATIONSHIPS | 4 | 11 | 36% |
|
||||
| ASSEMBLY | MOTION | 3 | 3 | 100% |
|
||||
| ASSEMBLY | MODIFY | 8 | 11 | 73% |
|
||||
| ASSEMBLY | CONTACT | 2 | 2 | 100% |
|
||||
| ASSEMBLY | CONFIGURE | 3 | 3 | 100% |
|
||||
| ASSEMBLY | CONSTRUCT | 19 | 20 | 95% |
|
||||
| ASSEMBLY | INSPECT | 12 | 25 | 48% |
|
||||
| ASSEMBLY | SELECT | 0 | 15 | 0% |
|
||||
| ASSEMBLY | POSITION | 2 | 2 | 100% |
|
||||
| PLASTIC | enclosure subset | 5 | 5 | 100% |
|
||||
|
||||
### Deferred tabs
|
||||
|
||||
| Tab | Panel | Live | Total | % |
|
||||
|---|---|---:|---:|---:|
|
||||
| SURFACE | CREATE | 9 | 25 | 36% |
|
||||
| SURFACE | MODIFY | 17 | 26 | 65% |
|
||||
| SURFACE | ASSEMBLE | 11 | 20 | 55% |
|
||||
| SURFACE | CONFIGURE | 3 | 3 | 100% |
|
||||
| SURFACE | CONSTRUCT | 19 | 20 | 95% |
|
||||
| SURFACE | INSPECT | 12 | 25 | 48% |
|
||||
| SURFACE | INSERT | 6 | 11 | 55% |
|
||||
| SURFACE | SELECT | 0 | 15 | 0% |
|
||||
| SURFACE | POSITION | 2 | 2 | 100% |
|
||||
| MESH | CREATE | 2 | 5 | 40% |
|
||||
| MESH | PREPARE | 0 | 4 | 0% |
|
||||
| MESH | MODIFY | 7 | 30 | 23% |
|
||||
| MESH | ASSEMBLE | 12 | 21 | 57% |
|
||||
| MESH | CONFIGURE | 3 | 3 | 100% |
|
||||
| MESH | CONSTRUCT | 19 | 20 | 95% |
|
||||
| MESH | INSPECT | 12 | 25 | 48% |
|
||||
| MESH | INSERT | 5 | 10 | 50% |
|
||||
| MESH | SELECT | 0 | 10 | 0% |
|
||||
| MESH | EXPORT | 0 | 1 | 0% |
|
||||
| MESH | POSITION | 2 | 2 | 100% |
|
||||
| FORM | CREATE | 2 | 14 | 14% |
|
||||
| FORM | MODIFY | 5 | 31 | 16% |
|
||||
| FORM | SYMMETRY | 0 | 6 | 0% |
|
||||
| FORM | UTILITIES | 0 | 5 | 0% |
|
||||
| FORM | CONSTRUCT | 19 | 20 | 95% |
|
||||
| FORM | INSPECT | 12 | 25 | 48% |
|
||||
| FORM | INSERT | 7 | 13 | 54% |
|
||||
| FORM | ASSEMBLE | 0 | 1 | 0% |
|
||||
| FORM | SELECT | 0 | 15 | 0% |
|
||||
| FORM | FINISH FORM | 0 | 1 | 0% |
|
||||
| PLASTIC | SETUP | 2 | 2 | 100% |
|
||||
| PLASTIC | CREATE | 27 | 35 | 77% |
|
||||
| PLASTIC | MODIFY | 19 | 32 | 59% |
|
||||
| PLASTIC | ASSEMBLE | 11 | 20 | 55% |
|
||||
| PLASTIC | CONFIGURE | 3 | 3 | 100% |
|
||||
| PLASTIC | CONSTRUCT | 19 | 20 | 95% |
|
||||
| PLASTIC | INSPECT | 12 | 26 | 46% |
|
||||
| PLASTIC | INSERT | 6 | 11 | 55% |
|
||||
| PLASTIC | SELECT | 0 | 15 | 0% |
|
||||
| PLASTIC | POSITION | 2 | 2 | 100% |
|
||||
| MANAGE | ASSIGN | 0 | 1 | 0% |
|
||||
| MANAGE | RELEASE | 0 | 2 | 0% |
|
||||
| MANAGE | BOM | 0 | 2 | 0% |
|
||||
| MANAGE | PROCESS MANAGEMENT | 0 | 3 | 0% |
|
||||
| MANAGE | TASK MANAGEMENT | 0 | 3 | 0% |
|
||||
| UTILITIES | MODELING TOOLS | 0 | 1 | 0% |
|
||||
| UTILITIES | MAKE | 0 | 1 | 0% |
|
||||
| UTILITIES | NEST | 0 | 1 | 0% |
|
||||
| UTILITIES | ADD-INS | 0 | 2 | 0% |
|
||||
| UTILITIES | UTILITY | 1 | 3 | 33% |
|
||||
| UTILITIES | INSPECT | 11 | 24 | 46% |
|
||||
| UTILITIES | CREATE PMI | 0 | 4 | 0% |
|
||||
| UTILITIES | SELECT | 0 | 15 | 0% |
|
||||
| UTILITIES | POSITION | 2 | 2 | 100% |
|
||||
|
||||
## Live (SOLID, SKETCH)
|
||||
|
||||
- SOLID › CREATE › Create Sketch
|
||||
- SOLID › CREATE › Extrude
|
||||
- SOLID › CREATE › Revolve
|
||||
- SOLID › CREATE › Sweep
|
||||
- SOLID › CREATE › Loft
|
||||
- SOLID › CREATE › Rib
|
||||
- SOLID › CREATE › Web
|
||||
- SOLID › CREATE › Emboss
|
||||
- SOLID › CREATE › Hole
|
||||
- SOLID › CREATE › Thread
|
||||
- SOLID › CREATE › Box
|
||||
- SOLID › CREATE › Cylinder
|
||||
- SOLID › CREATE › Sphere
|
||||
- SOLID › CREATE › Torus
|
||||
- SOLID › CREATE › Coil
|
||||
- SOLID › CREATE › Pipe
|
||||
- SOLID › CREATE › Bounding Solid
|
||||
- SOLID › CREATE › Rectangular Pattern
|
||||
- SOLID › CREATE › Circular Pattern
|
||||
- SOLID › CREATE › Pattern on Path
|
||||
- SOLID › CREATE › Mirror
|
||||
- SOLID › CREATE › Thicken
|
||||
- SOLID › CREATE › Joint Origin
|
||||
- SOLID › MODIFY › Press Pull
|
||||
- SOLID › MODIFY › Fillet
|
||||
- SOLID › MODIFY › Chamfer
|
||||
- SOLID › MODIFY › Shell
|
||||
- SOLID › MODIFY › Draft
|
||||
- SOLID › MODIFY › Scale
|
||||
- SOLID › MODIFY › Combine
|
||||
- SOLID › MODIFY › Offset Face
|
||||
- SOLID › MODIFY › Replace Face
|
||||
- SOLID › MODIFY › Split Face
|
||||
- SOLID › MODIFY › Split Body
|
||||
- SOLID › MODIFY › Move/Copy
|
||||
- SOLID › MODIFY › Align
|
||||
- SOLID › MODIFY › Delete
|
||||
- SOLID › MODIFY › Remove
|
||||
- SOLID › MODIFY › Physical Material
|
||||
- SOLID › MODIFY › Appearance
|
||||
- SOLID › MODIFY › Change Parameters
|
||||
- SOLID › MODIFY › Compute All
|
||||
- SOLID › ASSEMBLE › Insert Component
|
||||
- SOLID › ASSEMBLE › New Component
|
||||
- SOLID › ASSEMBLE › Joint
|
||||
- SOLID › ASSEMBLE › As-Built Joint
|
||||
- SOLID › ASSEMBLE › Rigid Group
|
||||
- SOLID › ASSEMBLE › Drive Joints
|
||||
- SOLID › ASSEMBLE › Motion Link
|
||||
- SOLID › ASSEMBLE › Motion Study
|
||||
- SOLID › ASSEMBLE › Enable Contact Sets
|
||||
- SOLID › ASSEMBLE › Enable All Contact
|
||||
- SOLID › ASSEMBLE › Disable Contact
|
||||
- SOLID › ASSEMBLE › New Contact Set
|
||||
- SOLID › CONFIGURE › Configure
|
||||
- SOLID › CONFIGURE › Display Configuration Table
|
||||
- SOLID › CONFIGURE › Create Configuration Rules
|
||||
- SOLID › CONSTRUCT › Offset Plane
|
||||
- SOLID › CONSTRUCT › Plane at Angle
|
||||
- SOLID › CONSTRUCT › Tangent Plane
|
||||
- SOLID › CONSTRUCT › Midplane
|
||||
- SOLID › CONSTRUCT › Perpendicular Plane
|
||||
- SOLID › CONSTRUCT › Plane Through Two Edges
|
||||
- SOLID › CONSTRUCT › Plane Through Three Points
|
||||
- SOLID › CONSTRUCT › Plane Along Path
|
||||
- SOLID › CONSTRUCT › Axis Through Cylinder/Cone/Torus
|
||||
- SOLID › CONSTRUCT › Axis Perpendicular To Face
|
||||
- SOLID › CONSTRUCT › Axis Through Two Planes
|
||||
- SOLID › CONSTRUCT › Axis Through Two Points
|
||||
- SOLID › CONSTRUCT › Axis Through Edge
|
||||
- SOLID › CONSTRUCT › Point At Vertex
|
||||
- SOLID › CONSTRUCT › Point Through Two Edges
|
||||
- SOLID › CONSTRUCT › Point Through Three Planes
|
||||
- SOLID › CONSTRUCT › Point At Center Of Circle/Sphere/Torus
|
||||
- SOLID › CONSTRUCT › Point At Edge And Plane
|
||||
- SOLID › CONSTRUCT › Point Along Path
|
||||
- SOLID › INSPECT › Measure
|
||||
- SOLID › INSPECT › Interference
|
||||
- SOLID › INSPECT › Section Analysis
|
||||
- SOLID › INSPECT › Curvature Comb Analysis
|
||||
- SOLID › INSPECT › Curvature Map Analysis
|
||||
- SOLID › INSPECT › Draft Analysis
|
||||
- SOLID › INSPECT › Environment Map Analysis
|
||||
- SOLID › INSPECT › Isocurve Analysis
|
||||
- SOLID › INSPECT › Zebra Analysis
|
||||
- SOLID › INSPECT › Accessibility Analysis
|
||||
- SOLID › INSPECT › Center of Mass
|
||||
- SOLID › INSPECT › Minimum Radius Analysis
|
||||
- SOLID › INSERT › Decal
|
||||
- SOLID › INSERT › Canvas
|
||||
- SOLID › INSERT › Insert SVG
|
||||
- SOLID › INSERT › Insert DXF
|
||||
- SOLID › INSERT › Insert Mesh
|
||||
- SOLID › INSERT › Insert Fastener
|
||||
- SOLID › POSITION › Capture Position
|
||||
- SOLID › POSITION › Revert Position
|
||||
- SKETCH › CREATE › Line
|
||||
- SKETCH › CREATE › Midpoint Line
|
||||
- SKETCH › CREATE › SketchConstrainer
|
||||
- SKETCH › CREATE › 2-Point Rectangle
|
||||
- SKETCH › CREATE › 3-Point Rectangle
|
||||
- SKETCH › CREATE › Center Rectangle
|
||||
- SKETCH › CREATE › Center Diameter Circle
|
||||
- SKETCH › CREATE › 2-Point Circle
|
||||
- SKETCH › CREATE › 3-Point Circle
|
||||
- SKETCH › CREATE › 2-Tangent Circle
|
||||
- SKETCH › CREATE › 3-Tangent Circle
|
||||
- SKETCH › CREATE › 3-Point Arc
|
||||
- SKETCH › CREATE › Center Point Arc
|
||||
- SKETCH › CREATE › Tangent Arc
|
||||
- SKETCH › CREATE › Circumscribed Polygon
|
||||
- SKETCH › CREATE › Inscribed Polygon
|
||||
- SKETCH › CREATE › Edge Polygon
|
||||
- SKETCH › CREATE › Ellipse
|
||||
- SKETCH › CREATE › Center to Center Slot
|
||||
- SKETCH › CREATE › Overall Slot
|
||||
- SKETCH › CREATE › Center Point Slot
|
||||
- SKETCH › CREATE › Three Point Arc Slot
|
||||
- SKETCH › CREATE › Center Point Arc Slot
|
||||
- SKETCH › CREATE › Fit Point Spline
|
||||
- SKETCH › CREATE › Control Point Spline
|
||||
- SKETCH › CREATE › Control Point Spline
|
||||
- SKETCH › CREATE › Conic Curve
|
||||
- SKETCH › CREATE › Point
|
||||
- SKETCH › CREATE › Text
|
||||
- SKETCH › CREATE › Fit Curves to Mesh Section
|
||||
- SKETCH › CREATE › Mirror
|
||||
- SKETCH › CREATE › Circular Pattern
|
||||
- SKETCH › CREATE › Rectangular Pattern
|
||||
- SKETCH › CREATE › Project
|
||||
- SKETCH › CREATE › Intersect
|
||||
- SKETCH › CREATE › Spun Profile
|
||||
- SKETCH › CREATE › Include 3D Geometry
|
||||
- SKETCH › CREATE › Project To Surface
|
||||
- SKETCH › CREATE › Intersection Curve
|
||||
- SKETCH › CREATE › Isoparametric Curve
|
||||
- SKETCH › CREATE › Sketch Dimension
|
||||
- SKETCH › MODIFY › Fillet
|
||||
- SKETCH › MODIFY › Equal Distance Chamfer
|
||||
- SKETCH › MODIFY › Distance and Angle Chamfer
|
||||
- SKETCH › MODIFY › Two Distance Chamfer
|
||||
- SKETCH › MODIFY › Blend Curve
|
||||
- SKETCH › MODIFY › Offset
|
||||
- SKETCH › MODIFY › Trim
|
||||
- SKETCH › MODIFY › Extend
|
||||
- SKETCH › MODIFY › Break
|
||||
- SKETCH › MODIFY › Sketch Scale
|
||||
- SKETCH › MODIFY › Move/Copy
|
||||
- SKETCH › MODIFY › Change Parameters
|
||||
- SKETCH › CONSTRAINTS › AutoConstrain
|
||||
- SKETCH › CONSTRAINTS › AutoConstrain from datum
|
||||
- SKETCH › CONSTRAINTS › Horizontal/Vertical
|
||||
- SKETCH › CONSTRAINTS › Coincident
|
||||
- SKETCH › CONSTRAINTS › Tangent
|
||||
- SKETCH › CONSTRAINTS › Equal
|
||||
- SKETCH › CONSTRAINTS › Parallel
|
||||
- SKETCH › CONSTRAINTS › Perpendicular
|
||||
- SKETCH › CONSTRAINTS › Fix/UnFix
|
||||
- SKETCH › CONSTRAINTS › MidPoint
|
||||
- SKETCH › CONSTRAINTS › Concentric
|
||||
- SKETCH › CONSTRAINTS › Collinear
|
||||
- SKETCH › CONSTRAINTS › Symmetry
|
||||
- SKETCH › CONSTRAINTS › Curvature
|
||||
- SKETCH › CONSTRAINTS › Polygon
|
||||
- SKETCH › CONFIGURE › Configure
|
||||
- SKETCH › CONFIGURE › Display Configuration Table
|
||||
- SKETCH › CONFIGURE › Create Configuration Rules
|
||||
- SKETCH › INSPECT › Measure
|
||||
- SKETCH › INSPECT › Interference
|
||||
- SKETCH › INSPECT › Section Analysis
|
||||
- SKETCH › INSPECT › Curvature Comb Analysis
|
||||
- SKETCH › INSPECT › Curvature Map Analysis
|
||||
- SKETCH › INSPECT › Draft Analysis
|
||||
- SKETCH › INSPECT › Environment Map Analysis
|
||||
- SKETCH › INSPECT › Isocurve Analysis
|
||||
- SKETCH › INSPECT › Zebra Analysis
|
||||
- SKETCH › INSPECT › Accessibility Analysis
|
||||
- SKETCH › INSPECT › Center of Mass
|
||||
- SKETCH › INSPECT › Minimum Radius Analysis
|
||||
- SKETCH › INSERT › Decal
|
||||
- SKETCH › INSERT › Canvas
|
||||
- SKETCH › INSERT › Insert SVG
|
||||
- SKETCH › INSERT › Insert DXF
|
||||
- SKETCH › INSERT › Insert Mesh
|
||||
- SKETCH › INSERT › Insert Component
|
||||
- SKETCH › INSERT › Insert Fastener
|
||||
- SKETCH › FINISH SKETCH › Finish Sketch
|
||||
- SKETCH › FINISH SKETCH › Finish with AutoConstrain
|
||||
|
||||
## Not yet (SOLID, SKETCH)
|
||||
|
||||
- SOLID › CREATE › Create Form
|
||||
- SOLID › CREATE › Derive
|
||||
- SOLID › CREATE › Automated Modeling
|
||||
- SOLID › CREATE › Geometric Pattern
|
||||
- SOLID › CREATE › Boundary Fill
|
||||
- SOLID › CREATE › Find Features
|
||||
- SOLID › CREATE › Fluid Volume
|
||||
- SOLID › CREATE › Create Base Feature
|
||||
- SOLID › CREATE › Create Linked PCB
|
||||
- SOLID › CREATE › Derive PCB
|
||||
- SOLID › CREATE › Create Unlinked PCB
|
||||
- SOLID › CREATE › Generate Timeline
|
||||
- SOLID › MODIFY › Edit Face
|
||||
- SOLID › MODIFY › Silhouette Split
|
||||
- SOLID › MODIFY › Arrange
|
||||
- SOLID › MODIFY › Remove Features
|
||||
- SOLID › MODIFY › Remove Faces
|
||||
- SOLID › MODIFY › Replace with Primitives
|
||||
- SOLID › MODIFY › Volumetric Lattice
|
||||
- SOLID › MODIFY › Volumetric Texture
|
||||
- SOLID › MODIFY › VolFieldModifyModelCommand
|
||||
- SOLID › MODIFY › Manage Materials
|
||||
- SOLID › MODIFY › Compute Unresolved
|
||||
- SOLID › MODIFY › Convert
|
||||
- SOLID › MODIFY › Bill of Materials
|
||||
- SOLID › ASSEMBLE › Duplicate With Joints
|
||||
- SOLID › ASSEMBLE › Constrain Components
|
||||
- SOLID › ASSEMBLE › Align Constraint
|
||||
- SOLID › ASSEMBLE › Angle Constraint
|
||||
- SOLID › ASSEMBLE › Center Constraint
|
||||
- SOLID › ASSEMBLE › Tangent Constraint
|
||||
- SOLID › ASSEMBLE › Joint Constraint
|
||||
- SOLID › ASSEMBLE › As-Built Constraint
|
||||
- SOLID › CONSTRUCT › User Coordinate System (UCS)
|
||||
- SOLID › INSPECT › Validate
|
||||
- SOLID › INSPECT › Component Connection Analysis
|
||||
- SOLID › INSPECT › DOF Analysis
|
||||
- SOLID › INSPECT › Edit Component Connection Analysis
|
||||
- SOLID › INSPECT › Fastener Stack Analysis
|
||||
- SOLID › INSPECT › Find Similar Components
|
||||
- SOLID › INSPECT › Navigator
|
||||
- SOLID › INSPECT › Display Component Colors
|
||||
- SOLID › INSPECT › Display Mesh Face Groups
|
||||
- SOLID › INSPECT › Assembly Statistics
|
||||
- SOLID › INSPECT › Change Summary
|
||||
- SOLID › INSPECT › History
|
||||
- SOLID › INSPECT › Sustainability Insights
|
||||
- SOLID › INSERT › Insert T-Spline
|
||||
- SOLID › INSERT › Insert Derive
|
||||
- SOLID › INSERT › Insert McMaster-Carr Component
|
||||
- SOLID › INSERT › Insert a manufacturer part
|
||||
- SOLID › INSERT › Insert TraceParts Supplier Components
|
||||
- SOLID › ASSEMBLE › Add To Assembly
|
||||
- SOLID › SELECT › Select
|
||||
- SOLID › SELECT › Window Selection
|
||||
- SOLID › SELECT › Freeform Selection
|
||||
- SOLID › SELECT › Paint Selection
|
||||
- SOLID › SELECT › Select By Name
|
||||
- SOLID › SELECT › Select By Boundary
|
||||
- SOLID › SELECT › Select By Size
|
||||
- SOLID › SELECT › Invert Selection
|
||||
- SOLID › SELECT › Seed And Boundary
|
||||
- SOLID › SELECT › Component Drag
|
||||
- SOLID › SELECT › Select Body Priority
|
||||
- SOLID › SELECT › Select Face Priority
|
||||
- SOLID › SELECT › Select Edge Priority
|
||||
- SOLID › SELECT › Select Component Priority
|
||||
- SOLID › SELECT › Selection Filters
|
||||
- SKETCH › INSPECT › Validate
|
||||
- SKETCH › INSPECT › Component Connection Analysis
|
||||
- SKETCH › INSPECT › DOF Analysis
|
||||
- SKETCH › INSPECT › Edit Component Connection Analysis
|
||||
- SKETCH › INSPECT › Fastener Stack Analysis
|
||||
- SKETCH › INSPECT › Find Similar Components
|
||||
- SKETCH › INSPECT › Navigator
|
||||
- SKETCH › INSPECT › Display Component Colors
|
||||
- SKETCH › INSPECT › Display Mesh Face Groups
|
||||
- SKETCH › INSPECT › Assembly Statistics
|
||||
- SKETCH › INSPECT › Change Summary
|
||||
- SKETCH › INSPECT › History
|
||||
- SKETCH › INSPECT › Sustainability Insights
|
||||
- SKETCH › INSERT › Insert T-Spline
|
||||
- SKETCH › INSERT › Duplicate With Joints
|
||||
- SKETCH › INSERT › Insert Derive
|
||||
- SKETCH › INSERT › Insert McMaster-Carr Component
|
||||
- SKETCH › INSERT › Insert a manufacturer part
|
||||
- SKETCH › INSERT › Insert TraceParts Supplier Components
|
||||
- SKETCH › ASSEMBLE › Add To Assembly
|
||||
- SKETCH › SELECT › Select
|
||||
- SKETCH › SELECT › Window Selection
|
||||
- SKETCH › SELECT › Freeform Selection
|
||||
- SKETCH › SELECT › Paint Selection
|
||||
- SKETCH › SELECT › Select By Name
|
||||
- SKETCH › SELECT › Select By Boundary
|
||||
- SKETCH › SELECT › Select By Size
|
||||
- SKETCH › SELECT › Invert Selection
|
||||
- SKETCH › SELECT › Seed And Boundary
|
||||
- SKETCH › SELECT › Component Drag
|
||||
- SKETCH › SELECT › Select Body Priority
|
||||
- SKETCH › SELECT › Select Face Priority
|
||||
- SKETCH › SELECT › Select Edge Priority
|
||||
- SKETCH › SELECT › Select Component Priority
|
||||
- SKETCH › SELECT › Selection Filters
|
||||
@@ -1,7 +1,7 @@
|
||||
# WIP branch reconciliation (#6)
|
||||
|
||||
The branches predate the dotted command IDs. Their remaining changes were ported through
|
||||
`crates/engine/src/legacy_ids.rs` and reconciled with the current implementation.
|
||||
The branches predate the dotted command IDs. Their remaining changes were ported to the
|
||||
dotted ids and reconciled with the current implementation.
|
||||
|
||||
| Branches | Result |
|
||||
|---|---|
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,184 +0,0 @@
|
||||
# Fusion catalog command id -> SolveCraft command id, for `cargo xtask parity` only (observation data).
|
||||
# A catalog command is live when its SolveCraft command is registered.
|
||||
SketchCreate sketch.create
|
||||
Extrude solid.extrude
|
||||
Revolve solid.revolve
|
||||
Sweep solid.sweep
|
||||
SolidLoft solid.loft
|
||||
FusionRibCommand solid.rib
|
||||
FusionWebCommand solid.web
|
||||
EmbossCmd solid.emboss
|
||||
FusionHoleCommand solid.hole
|
||||
FusionThreadCommand solid.thread
|
||||
PrimitiveBox solid.box
|
||||
PrimitiveCylinder solid.cylinder
|
||||
PrimitiveSphere solid.sphere
|
||||
PrimitiveTorus solid.torus
|
||||
PrimitiveCoil solid.coil
|
||||
PrimitivePipe solid.pipe
|
||||
StockModelCommand solid.bounding_solid
|
||||
PatternRectangular solid.pattern.rectangular
|
||||
PatternCircular solid.pattern.circular
|
||||
PatternOnPath solid.pattern.path
|
||||
MirrorCommand solid.mirror
|
||||
FusionSurfaceThickenCommand surface.thicken
|
||||
JointOrigin joint.origin
|
||||
FusionPressPullCommand solid.press_pull
|
||||
FusionFilletEdgesCommand solid.fillet
|
||||
FusionChamferCommand solid.chamfer
|
||||
FusionShellBodyCommand solid.shell
|
||||
FusionDraftCommand solid.draft
|
||||
ModifyScale solid.scale
|
||||
FusionCombineCommand solid.combine
|
||||
FusionOffsetFacesCommand solid.offset_face
|
||||
FusionReplaceFaceCommand solid.replace_face
|
||||
FusionSplitFaceCommand solid.split_face
|
||||
FusionSplitBodyCommand solid.split_body
|
||||
FusionMoveCommand solid.move
|
||||
AlignCmd solid.align
|
||||
FusionDeleteCommand timeline.delete
|
||||
SoftDeleteCommand solid.remove
|
||||
PhysicalMaterialCommand material.assign
|
||||
AppearanceCommand appearance.assign
|
||||
ChangeParameterCommand parameters.change
|
||||
FusionComputeAllCommand timeline.compute_all
|
||||
FusionImportCommandFromToolbar file.insert_step
|
||||
FusionCreateNewComponentCommand component.create
|
||||
JointAssembleCmdNew joint.create
|
||||
JointAsBuiltCmd joint.as_built
|
||||
RigidGroupCmd joint.rigid_group
|
||||
FusionMoveJointsCommand joint.drive
|
||||
FusionMotionRelationshipCommand joint.motion_link
|
||||
FusionMotionStudyCommand motion.study
|
||||
EnableContactSetsCmd contact.enable_sets
|
||||
EnableAllContactCmd contact.enable_all
|
||||
DisableAllContactCmd contact.disable_all
|
||||
ContactSetCmd contact.create
|
||||
FusionStartDesignConfigModeCmd config.configure
|
||||
FusionShowDesignConfigPanelCmd config.table
|
||||
FusionConfigurationRulesCmd config.rules
|
||||
ConstructionPlaneOffsetFromPlaneCommand construct.plane.offset
|
||||
ConstructionPlaneAtAngleCommand construct.plane.at_angle
|
||||
ConstructionTangentPlaneCommand construct.plane.tangent
|
||||
ConstructionMidPlaneCommand construct.plane.midplane
|
||||
ConstructionPlaneFromTwoEdgesCommand construct.plane.two_edges
|
||||
ConstructionPlaneFromThreePointsCommand construct.plane.three_points
|
||||
ConstructionPlaneAlongPathCommand construct.plane.along_path
|
||||
ConstructionAxisThroughCylinderCommand construct.axis.through_cylinder
|
||||
ConstructionAxisNormalToFaceCommand construct.axis.normal_to_face
|
||||
ConstructionAxisFromTwoPlanesCommand construct.axis.two_planes
|
||||
ConstructionAxisThroughTwoPointsCommand construct.axis.two_points
|
||||
ConstructionAxisThroughEdgeCommand construct.axis.edge
|
||||
ConstructionPointFromPointCommand construct.point.vertex
|
||||
ConstructionPointThroughTwoEdgesCommand construct.point.two_edges
|
||||
ConstructionPointFromThreePlanesCommand construct.point.three_planes
|
||||
ConstructionPointFromCircleOrSphereCommand construct.point.center
|
||||
ConstructionPointAtEdgeAndPlaneCommand construct.point.edge_plane
|
||||
ConstructionPointAlongPathCommand construct.point.along_path
|
||||
MeasureCommand inspect.measure
|
||||
InterferenceCheckCommand inspect.interference
|
||||
FusionHalfSectionViewCommand inspect.section
|
||||
FusionCurvatureCombAnalysisCommand inspect.curvature_comb
|
||||
FusionCurvatureMapAnalysisCommand inspect.curvature_map
|
||||
FusionDraftAnalysisCommand inspect.draft
|
||||
FusionEnvironmentMapAnalysisCommand inspect.environment_map
|
||||
FusionIsoCurveAnalysisCommand inspect.isocurve
|
||||
FusionZebraAnalysisCommand inspect.zebra
|
||||
FusionAccessibilityAnalysisCommand inspect.accessibility
|
||||
FusionCenterOfMassCommand inspect.center_of_mass
|
||||
FusionMinimumRadiusAnalysisCommand inspect.minimum_radius
|
||||
FusionAddEditDecalCommand canvas.decal
|
||||
FusionAddCanvasCommand canvas.insert
|
||||
SketchImportSVG sketch.insert_svg
|
||||
ImportDxfFileCommand sketch.insert_dxf
|
||||
ParaMeshInsertAlignCommand file.insert_mesh
|
||||
FusionFastenersCommand parts.fastener
|
||||
SnapshotCmd component.capture_position
|
||||
AsBuiltPositionsCmd component.revert_position
|
||||
DrawPolyline sketch.line
|
||||
SketchMidpointLine sketch.line.midpoint
|
||||
SketchConstrainer sketch.constrainer
|
||||
ShapeRectangleTwoPoint sketch.rectangle.two_point
|
||||
ShapeRectangleThreePoint sketch.rectangle.three_point
|
||||
ShapeRectangleCenter sketch.rectangle.center
|
||||
CircleCenterRadius sketch.circle.center
|
||||
CircleTwoPoint sketch.circle.two_point
|
||||
CircleThreePoint sketch.circle.three_point
|
||||
CircleTanTanRadius sketch.circle.two_tangent
|
||||
CircleThreeTangent sketch.circle.three_tangent
|
||||
ArcThreePoint sketch.arc.three_point
|
||||
ArcCenterTwoPoint sketch.arc.center_point
|
||||
ArcTangent sketch.arc.tangent
|
||||
ShapePolygonCircumscribed sketch.polygon.circumscribed
|
||||
ShapePolygonInscribed sketch.polygon.inscribed
|
||||
ShapePolygonEdge sketch.polygon.edge
|
||||
CircleElipse sketch.ellipse
|
||||
ShapeSlotCenterToCenter sketch.slot.center_to_center
|
||||
ShapeSlotOverall sketch.slot.overall
|
||||
ShapeSlotCenterPoint sketch.slot.center_point
|
||||
ShapeArcSlotThreePoint sketch.slot.arc_three_point
|
||||
ShapeArcSlotCenterTwoPoint sketch.slot.arc_center
|
||||
DrawSpline sketch.spline.fit_point
|
||||
DrawCVMSpline3D sketch.spline.control_point
|
||||
DrawCVMSpline5D sketch.spline.control_point_5
|
||||
ConicCurveCmd sketch.conic
|
||||
DrawPoint sketch.point
|
||||
MTextCmd sketch.text
|
||||
FitCurvesToSectionCommand sketch.fit_curves_to_section
|
||||
MirrorSketchCommand sketch.mirror
|
||||
CircularSketchPatternCommand sketch.pattern.circular
|
||||
RectangularSketchPatternCommand sketch.pattern.rectangular
|
||||
ProjectNewCmd sketch.project
|
||||
IntersectCmd sketch.intersect
|
||||
SpunProfileCmd sketch.spun_profile
|
||||
Include3DGeometry sketch.include_3d
|
||||
ProjectToSurface sketch.project_to_surface
|
||||
IntersectionCurve sketch.intersection_curve
|
||||
SketchIsoparametricCurve sketch.isoparametric_curve
|
||||
SketchDimension sketch.dimension
|
||||
FilletSketchCmd sketch.fillet
|
||||
ChamferSketchEqualDistance sketch.chamfer.equal_distance
|
||||
ChamferSketchDistanceAngle sketch.chamfer.distance_angle
|
||||
ChamferSketchDistanceDistance sketch.chamfer.two_distance
|
||||
BlendG1CurveSketchCmd sketch.blend_curve
|
||||
Offset sketch.offset
|
||||
TrimSketchCmd sketch.trim
|
||||
ExtendSketchCmd sketch.extend
|
||||
BreakSketchCmd sketch.break
|
||||
SketchScaleCmd sketch.scale
|
||||
SketchAutoConstraintAndDimCmd sketch.auto_constrain
|
||||
SketchAutoConstraintAndDimFromDatumCmd sketch.auto_constrain_from_datum
|
||||
ConstraintHorizontalVertical sketch.constraint.horizontal_vertical
|
||||
ConstraintCoincident sketch.constraint.coincident
|
||||
ConstraintTangent sketch.constraint.tangent
|
||||
ConstraintEqual sketch.constraint.equal
|
||||
ConstraintParallel sketch.constraint.parallel
|
||||
ConstraintPerpendicular sketch.constraint.perpendicular
|
||||
ConstraintFix sketch.constraint.fix
|
||||
ConstraintMidPoint sketch.constraint.midpoint
|
||||
ConstraintConcentric sketch.constraint.concentric
|
||||
ConstraintCollinear sketch.constraint.collinear
|
||||
ConstraintSymmetry sketch.constraint.symmetry
|
||||
ConstraintSmooth sketch.constraint.curvature
|
||||
SketchPolygonConstraintCmd sketch.constraint.polygon
|
||||
SketchStop sketch.finish
|
||||
SketchAutoConstrainAndFinish sketch.finish_auto_constrain
|
||||
FusionSurfacePatchCommand surface.patch
|
||||
FusionSurfaceTrimCommand surface.trim
|
||||
FusionExtendCommand surface.extend
|
||||
FusionSurfaceStitchCommand surface.stitch
|
||||
FusionSheetMetalFlangeCommand sheet.flange
|
||||
FusionSheetMetalHemFlangeCommand sheet.hem
|
||||
SheetMetalFoldCmd sheet.fold
|
||||
ConvertToSheetMetalCmd sheet.convert
|
||||
FusionSheetMetalFlatPatternCmd sheet.flat_pattern
|
||||
FusionSheetmetalUnfoldCommand sheet.unfold
|
||||
FusionSheetMetalRulesCommand sheet.manage_rules
|
||||
FusionAssignPlasticRuleCommand plastic.assign_rule
|
||||
FusionManagePlasticRuleCommand plastic.manage_rules
|
||||
FusionBossCommand plastic.boss
|
||||
FusionSnapFitCommand plastic.snap_fit
|
||||
FusionLipCommand plastic.lip
|
||||
FusionRestCommand plastic.rest
|
||||
ConstructionPlanePerpendicularToPlaneCommand construct.plane.perpendicular
|
||||
ParaMeshConvertCommand mesh.convert
|
||||
|
@@ -0,0 +1,104 @@
|
||||
//! `cargo xtask features`: SolidCraft's own feature checklist, `docs/features.md`.
|
||||
//!
|
||||
//! The page lists every registered command by area (the first part of its dotted id), with its
|
||||
//! label, id and toolbar place. It comes only from SolidCraft's command registry
|
||||
//! (`solvecraft-cli commands`), so it can't drift from what the program does; it compares with
|
||||
//! nothing else.
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use serde_json::Value;
|
||||
|
||||
/// Areas in the order the page lists them (id prefix, heading). Other prefixes follow,
|
||||
/// alphabetically, under their prefix.
|
||||
const AREAS: &[(&str, &str)] = &[
|
||||
("sketch", "Sketch"),
|
||||
("solid", "Solid modelling"),
|
||||
("surface", "Surfaces"),
|
||||
("construct", "Construction geometry"),
|
||||
("sheet", "Sheet metal"),
|
||||
("plastic", "Plastic parts"),
|
||||
("component", "Components"),
|
||||
("joint", "Assembly joints"),
|
||||
("config", "Configurations"),
|
||||
("timeline", "Timeline"),
|
||||
("inspect", "Inspect"),
|
||||
("file", "Files"),
|
||||
("doc", "Documents"),
|
||||
("edit", "Edit"),
|
||||
];
|
||||
|
||||
pub fn run(root: &Path) -> Result<(), String> {
|
||||
let out = crate::cargo()
|
||||
.args(["run", "-q", "--release", "-p", "solvecraft-cli", "--", "commands"])
|
||||
.output()
|
||||
.map_err(|e| format!("solvecraft-cli: {e}"))?;
|
||||
if !out.status.success() {
|
||||
return Err(format!("solvecraft-cli commands failed:\n{}", String::from_utf8_lossy(&out.stderr)));
|
||||
}
|
||||
let cmds: Value = serde_json::from_slice(&out.stdout).map_err(|e| format!("commands JSON: {e}"))?;
|
||||
let list = cmds.as_array().map(Vec::as_slice).unwrap_or_default();
|
||||
let md = page(list);
|
||||
std::fs::write(root.join("docs/features.md"), md).map_err(|e| format!("docs/features.md: {e}"))?;
|
||||
println!("features: {} commands → docs/features.md", list.len());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn area(id: &str) -> &str {
|
||||
id.split('.').next().unwrap_or_default()
|
||||
}
|
||||
|
||||
/// The checklist page for the registry's commands.
|
||||
pub fn page(cmds: &[Value]) -> String {
|
||||
let s = |c: &Value, k: &str| c[k].as_str().unwrap_or_default().to_string();
|
||||
let mut prefixes: Vec<String> = cmds.iter().map(|c| area(&s(c, "id")).to_string()).collect();
|
||||
prefixes.sort();
|
||||
prefixes.dedup();
|
||||
let mut order: Vec<(String, String)> =
|
||||
AREAS.iter().filter(|(p, _)| prefixes.iter().any(|x| x == p)).map(|(p, h)| (p.to_string(), h.to_string())).collect();
|
||||
for p in prefixes.iter().filter(|p| !AREAS.iter().any(|(a, _)| a == p)) {
|
||||
order.push((p.clone(), format!("`{p}.*`")));
|
||||
}
|
||||
let mut md = format!(
|
||||
"# Features\n\nSolidCraft's commands by area, generated by `cargo xtask features` from the command registry \
|
||||
(`solvecraft-cli commands`). **{} commands.** Every command runs the same way from the toolbar, a script, \
|
||||
`solvecraft-cli exec <id> '<json>'`, the control channel and MCP; parameters are in the \
|
||||
[command reference](book/src/reference/commands.md) (`cargo xtask book`). Status and plans: [ROADMAP](../ROADMAP.md).\n",
|
||||
cmds.len()
|
||||
);
|
||||
for (prefix, heading) in &order {
|
||||
let in_area: Vec<&Value> = cmds.iter().filter(|c| area(&s(c, "id")) == prefix).collect();
|
||||
md += &format!("\n## {heading} ({})\n\n| Command | Id | Toolbar |\n|---|---|---|\n", in_area.len());
|
||||
for c in in_area {
|
||||
let place = match (s(c, "tab"), s(c, "panel")) {
|
||||
(t, _) if t.is_empty() => "–".to_string(),
|
||||
(t, p) if p.is_empty() => t,
|
||||
(t, p) => format!("{t} › {p}"),
|
||||
};
|
||||
let key = c["shortcut"].as_str().map(|k| format!(" ({k})")).unwrap_or_default();
|
||||
md += &format!("| {}{key} | `{}` | {place} |\n", s(c, "label").replace('|', "/"), s(c, "id"));
|
||||
}
|
||||
}
|
||||
md
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn page_groups_by_area() {
|
||||
let cmds: Value = serde_json::from_str(
|
||||
r#"[{"id":"solid.extrude","label":"Extrude","tab":"SOLID","panel":"CREATE","shortcut":"E"},
|
||||
{"id":"sketch.line","label":"Line","tab":"SKETCH","panel":"CREATE"},
|
||||
{"id":"view.fit","label":"Fit","tab":"","panel":""}]"#,
|
||||
)
|
||||
.unwrap();
|
||||
let md = page(cmds.as_array().unwrap());
|
||||
assert!(md.contains("**3 commands.**"));
|
||||
let (sk, so, other) = (md.find("## Sketch (1)").unwrap(), md.find("## Solid modelling (1)").unwrap(), md.find("## `view.*` (1)").unwrap());
|
||||
assert!(sk < so && so < other);
|
||||
assert!(md.contains("| Extrude (E) | `solid.extrude` | SOLID › CREATE |"));
|
||||
assert!(md.contains("| Fit | `view.fit` | – |"));
|
||||
}
|
||||
}
|
||||
+3
-5
@@ -5,9 +5,9 @@
|
||||
|
||||
mod assets;
|
||||
mod book;
|
||||
mod features;
|
||||
mod layers;
|
||||
mod licences;
|
||||
mod parity;
|
||||
mod test;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
@@ -19,9 +19,7 @@ usage: cargo xtask <command>
|
||||
commands:
|
||||
layers enforce the crate dependency layering (plan/architecture.md §3)
|
||||
assets check that every non-code asset file is attributed in ATTRIBUTION.md
|
||||
parity [--refresh]
|
||||
recompute Fusion command parity in docs/parity.md (--refresh rebuilds
|
||||
xtask/data/fusion-catalog.tsv from plan/fusion/menu-tree.json)
|
||||
features list SolidCraft's commands by area in docs/features.md (from the registry)
|
||||
oracle [--cli BIN]
|
||||
replay the reference tests (tests/oracle/*/recipe.json), compare with each
|
||||
case's expected.json and write docs/oracle.md (--cli: a solvecraft-cli
|
||||
@@ -46,7 +44,7 @@ fn main() -> ExitCode {
|
||||
let result = match args.first().map(String::as_str) {
|
||||
Some("layers") => cmd_layers(),
|
||||
Some("assets") => assets::run(&root()),
|
||||
Some("parity") => parity::run(&root(), rest.contains(&"--refresh")),
|
||||
Some("features") => features::run(&root()),
|
||||
Some("oracle") => cmd_oracle(rest.iter().position(|a| *a == "--cli").and_then(|i| rest.get(i + 1)).copied()),
|
||||
Some("book") => book::run(&root(), !rest.contains(&"--no-build")),
|
||||
Some("licences") => licences::run(&root(), rest.contains(&"--check")),
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
//! `cargo xtask parity`: Fusion Design-workspace command parity.
|
||||
//!
|
||||
//! `xtask/data/fusion-catalog.tsv` lists the toolbar commands of Fusion's Design workspace as
|
||||
//! `tab \t panel \t command id \t command name` (ids and names only, nothing else). It is
|
||||
//! derived from the local, uncommitted `plan/fusion/menu-tree.json` with `--refresh`. A catalog
|
||||
//! entry is live when SolidCraft registers the command `xtask/data/fusion-ids.tsv` maps its id to
|
||||
//! (SolidCraft uses its own ids).
|
||||
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
use serde_json::Value;
|
||||
|
||||
/// Design workspace tabs in the catalog (menu-tree tab id, display name).
|
||||
const TABS: &[(&str, &str)] = &[
|
||||
("SolidTab", "SOLID"),
|
||||
("SketchTab", "SKETCH"),
|
||||
("SurfaceTab", "SURFACE"),
|
||||
("ParaMeshOuterTab", "MESH"),
|
||||
("FormTab", "FORM"),
|
||||
("SheetMetalTab", "SHEET METAL"),
|
||||
("PlasticTab", "PLASTIC"),
|
||||
("AssemblyTab", "ASSEMBLY"),
|
||||
("ManageTab", "MANAGE"),
|
||||
("ToolsTab", "UTILITIES"),
|
||||
];
|
||||
|
||||
/// The tabs the headline number counts (now: SOLID and SKETCH).
|
||||
const HEADLINE: &[&str] = &["SOLID", "SKETCH"];
|
||||
|
||||
/// The owner's scope: these tabs (and the PLASTIC subset below) count toward the in-scope
|
||||
/// figure; the rest of Fusion is deferred and listed separately.
|
||||
const IN_SCOPE_TABS: &[&str] = &["SOLID", "SKETCH", "ASSEMBLY", "SHEET METAL"];
|
||||
/// The PLASTIC commands in scope (enclosure features).
|
||||
/// (SolidCraft ids, matched through the catalog-id map.)
|
||||
const PLASTIC_SUBSET: &[&str] = &["plastic.boss", "solid.rib", "solid.web", "plastic.lip", "plastic.snap_fit"];
|
||||
|
||||
/// Catalog id → SolidCraft id.
|
||||
fn id_map(s: &str) -> std::collections::HashMap<String, String> {
|
||||
s.lines()
|
||||
.filter(|l| !l.starts_with('#') && !l.trim().is_empty())
|
||||
.filter_map(|l| l.split_once('\t').map(|(a, b)| (a.trim().to_string(), b.trim().to_string())))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn in_plastic_subset(e: &Entry, map: &std::collections::HashMap<String, String>) -> bool {
|
||||
e.tab == "PLASTIC" && map.get(&e.id).is_some_and(|ours| PLASTIC_SUBSET.contains(&ours.as_str()))
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Entry {
|
||||
pub tab: String,
|
||||
pub panel: String,
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
fn clean(s: &str) -> String {
|
||||
s.replace(['\t', '\n', '\r'], " ").trim().to_string()
|
||||
}
|
||||
|
||||
fn walk(controls: &[Value], defs: &[Value], tab: &str, panel: &str, out: &mut Vec<Entry>) {
|
||||
for c in controls {
|
||||
match c["type"].as_str() {
|
||||
Some("CommandControl") => {
|
||||
let id = c["command"]["id"].as_str().or(c["id"].as_str()).unwrap_or("");
|
||||
if id.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let name = c["command"]["name"]
|
||||
.as_str()
|
||||
.filter(|n| !n.is_empty())
|
||||
.or_else(|| defs.iter().find(|d| d["id"].as_str() == Some(id)).and_then(|d| d["name"].as_str()))
|
||||
.unwrap_or(id);
|
||||
if !out.iter().any(|e| e.tab == tab && e.id == id) {
|
||||
out.push(Entry { tab: tab.into(), panel: panel.into(), id: clean(id), name: clean(name) });
|
||||
}
|
||||
}
|
||||
Some("DropDownControl") => walk(c["controls"].as_array().map(Vec::as_slice).unwrap_or(&[]), defs, tab, panel, out),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Catalog entries from Fusion's menu-tree JSON.
|
||||
pub fn from_menu_tree(v: &Value) -> Vec<Entry> {
|
||||
let defs = v["commandDefinitions"].as_array().map(Vec::as_slice).unwrap_or(&[]);
|
||||
let mut out = Vec::new();
|
||||
for (tid, tname) in TABS {
|
||||
let tab = &v["tabs"][format!("DesignProductType/{tid}")];
|
||||
for p in tab["panels"].as_array().into_iter().flatten() {
|
||||
let panel = clean(p["name"].as_str().unwrap_or("")).to_uppercase();
|
||||
walk(p["controls"].as_array().map(Vec::as_slice).unwrap_or(&[]), defs, tname, &panel, &mut out);
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
pub fn parse_catalog(s: &str) -> Vec<Entry> {
|
||||
s.lines()
|
||||
.filter(|l| !l.starts_with('#') && !l.trim().is_empty())
|
||||
.filter_map(|l| {
|
||||
let mut it = l.split('\t');
|
||||
Some(Entry { tab: it.next()?.into(), panel: it.next()?.into(), id: it.next()?.into(), name: it.next().unwrap_or("").into() })
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn run(root: &Path, refresh: bool) -> Result<(), String> {
|
||||
let cat_path = root.join("xtask/data/fusion-catalog.tsv");
|
||||
if refresh {
|
||||
let mt = root.join("plan/fusion/menu-tree.json");
|
||||
let s = std::fs::read_to_string(&mt).map_err(|e| format!("{}: {e}", mt.display()))?;
|
||||
let v: Value = serde_json::from_str(&s).map_err(|e| format!("menu-tree.json: {e}"))?;
|
||||
let entries = from_menu_tree(&v);
|
||||
let mut out = String::from(
|
||||
"# Fusion Design workspace toolbar: tab, panel, command id, command name (ids and names only).\n# Regenerate with `cargo xtask parity --refresh` (needs the local plan/fusion/menu-tree.json).\n",
|
||||
);
|
||||
for e in &entries {
|
||||
out += &format!("{}\t{}\t{}\t{}\n", e.tab, e.panel, e.id, e.name);
|
||||
}
|
||||
std::fs::create_dir_all(root.join("xtask/data")).map_err(|e| e.to_string())?;
|
||||
std::fs::write(&cat_path, out).map_err(|e| format!("{}: {e}", cat_path.display()))?;
|
||||
println!("parity: catalog refreshed with {} entries", entries.len());
|
||||
}
|
||||
let catalog = parse_catalog(&std::fs::read_to_string(&cat_path).map_err(|e| format!("{}: {e}", cat_path.display()))?);
|
||||
let out = Command::new(std::env::var("CARGO").unwrap_or_else(|_| "cargo".into()))
|
||||
.current_dir(root)
|
||||
.args(["run", "-q", "--release", "-p", "solvecraft-cli", "--", "commands"])
|
||||
.output()
|
||||
.map_err(|e| format!("solvecraft-cli: {e}"))?;
|
||||
let cmds: Value = serde_json::from_slice(&out.stdout).map_err(|e| format!("commands JSON: {e}"))?;
|
||||
let ids: Vec<String> = cmds.as_array().into_iter().flatten().filter_map(|c| c["id"].as_str().map(str::to_string)).collect();
|
||||
let map_path = root.join("xtask/data/fusion-ids.tsv");
|
||||
let map = id_map(&std::fs::read_to_string(&map_path).map_err(|e| format!("{}: {e}", map_path.display()))?);
|
||||
let live = |e: &Entry| map.get(&e.id).is_some_and(|ours| ids.contains(ours));
|
||||
let in_scope = |e: &Entry| IN_SCOPE_TABS.contains(&e.tab.as_str()) || in_plastic_subset(e, &map);
|
||||
let pct = |a: usize, b: usize| if b == 0 { 0.0 } else { 100.0 * a as f64 / b as f64 };
|
||||
|
||||
let head: Vec<&Entry> = catalog.iter().filter(|e| HEADLINE.contains(&e.tab.as_str())).collect();
|
||||
let head_live = head.iter().filter(|e| live(e)).count();
|
||||
let all_live = catalog.iter().filter(|e| live(e)).count();
|
||||
let scope: Vec<&Entry> = catalog.iter().filter(|e| in_scope(e)).collect();
|
||||
let scope_live = scope.iter().filter(|e| live(e)).count();
|
||||
let mut md = format!(
|
||||
"# Fusion command parity\n\nGenerated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the toolbar commands of Fusion's Design workspace, ids and names only) and the live command registry (`solvecraft-cli commands`). A command counts as live when SolidCraft registers the same command id. This measures breadth, not depth; see ROADMAP.md and docs/oracle.md for depth.\n\n**In scope (SOLID, SKETCH, ASSEMBLY, SHEET METAL, PLASTIC enclosure subset): {scope_live} / {} commands live ({:.0}%).** SOLID + SKETCH: {head_live} / {} ({:.0}%). Registered commands: {}.\n\nDeferred until further notice (not in the in-scope figure): MESH, FORM, SURFACE beyond what solids need, PCB, render, animation, simulation, manufacture, drawings, MANAGE, UTILITIES and the rest of PLASTIC. All Design tabs together: {all_live} / {} ({:.0}%).\n\n| Tab | Panel | Live | Total | % |\n|---|---|---:|---:|---:|\n",
|
||||
scope.len(),
|
||||
pct(scope_live, scope.len()),
|
||||
head.len(),
|
||||
pct(head_live, head.len()),
|
||||
ids.len(),
|
||||
catalog.len(),
|
||||
pct(all_live, catalog.len()),
|
||||
);
|
||||
let mut groups: Vec<(String, String, usize, usize)> = Vec::new();
|
||||
for e in &catalog {
|
||||
let l = usize::from(live(e));
|
||||
match groups.iter_mut().find(|g| g.0 == e.tab && g.1 == e.panel) {
|
||||
Some(g) => {
|
||||
g.2 += l;
|
||||
g.3 += 1;
|
||||
}
|
||||
None => groups.push((e.tab.clone(), e.panel.clone(), l, 1)),
|
||||
}
|
||||
}
|
||||
for (t, p, l, n) in groups.iter().filter(|g| IN_SCOPE_TABS.contains(&g.0.as_str())) {
|
||||
md += &format!("| {t} | {p} | {l} | {n} | {:.0}% |\n", pct(*l, *n));
|
||||
}
|
||||
let plastic: Vec<&Entry> = catalog.iter().filter(|e| in_plastic_subset(e, &map)).collect();
|
||||
md += &format!(
|
||||
"| PLASTIC | enclosure subset | {} | {} | {:.0}% |\n",
|
||||
plastic.iter().filter(|e| live(e)).count(),
|
||||
plastic.len(),
|
||||
pct(plastic.iter().filter(|e| live(e)).count(), plastic.len())
|
||||
);
|
||||
md += "\n### Deferred tabs\n\n| Tab | Panel | Live | Total | % |\n|---|---|---:|---:|---:|\n";
|
||||
for (t, p, l, n) in groups.iter().filter(|g| !IN_SCOPE_TABS.contains(&g.0.as_str())) {
|
||||
md += &format!("| {t} | {p} | {l} | {n} | {:.0}% |\n", pct(*l, *n));
|
||||
}
|
||||
md += "\n## Live (SOLID, SKETCH)\n\n";
|
||||
for e in head.iter().filter(|e| live(e)) {
|
||||
md += &format!("- {} › {} › {}\n", e.tab, e.panel, e.name);
|
||||
}
|
||||
md += "\n## Not yet (SOLID, SKETCH)\n\n";
|
||||
for e in head.iter().filter(|e| !live(e)) {
|
||||
md += &format!("- {} › {} › {}\n", e.tab, e.panel, e.name);
|
||||
}
|
||||
std::fs::write(root.join("docs/parity.md"), md).map_err(|e| format!("docs/parity.md: {e}"))?;
|
||||
println!(
|
||||
"parity: in scope {scope_live}/{} ({:.0}%), SOLID+SKETCH {head_live}/{} ({:.0}%), all tabs {all_live}/{} → docs/parity.md",
|
||||
scope.len(),
|
||||
pct(scope_live, scope.len()),
|
||||
head.len(),
|
||||
pct(head_live, head.len()),
|
||||
catalog.len()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn catalog_from_menu_tree() {
|
||||
let v: Value = serde_json::from_str(
|
||||
r#"{"commandDefinitions":[{"id":"B","name":"Bee"}],"tabs":{"DesignProductType/SolidTab":{"panels":[{"name":"Create","controls":[
|
||||
{"type":"CommandControl","id":"A","command":{"id":"A","name":"Aye"}},
|
||||
{"type":"SeparatorControl","id":"s"},
|
||||
{"type":"DropDownControl","id":"d","controls":[{"type":"CommandControl","id":"B","command":{"id":"B"}}]}]}]}}}"#,
|
||||
)
|
||||
.unwrap();
|
||||
let e = from_menu_tree(&v);
|
||||
assert_eq!(e.len(), 2);
|
||||
assert_eq!((e[0].tab.as_str(), e[0].panel.as_str(), e[0].id.as_str(), e[0].name.as_str()), ("SOLID", "CREATE", "A", "Aye"));
|
||||
assert_eq!(e[1].name, "Bee");
|
||||
let tsv = "# c\nSOLID\tCREATE\tA\tAye\n";
|
||||
assert_eq!(parse_catalog(tsv).len(), 1);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user