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
|
## Start every session here
|
||||||
1. Read `plan/STATUS.md` (current milestone, next task), then the task in `plan/execution-plan.md`
|
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/`
|
and the relevant `plan/architecture.md` section.
|
||||||
(`menu-tree.json` is Fusion's toolbar dump).
|
|
||||||
2. Kernel and library decisions: `plan/adr/0001-geometry-kernel.md` (what we may depend on, what
|
2. Kernel and library decisions: `plan/adr/0001-geometry-kernel.md` (what we may depend on, what
|
||||||
is rejected for licence reasons).
|
is rejected for licence reasons).
|
||||||
3. Follow the autonomous operation protocol (`plan/execution-plan.md` §6). Don't stop to ask
|
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)]`.
|
`#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]`.
|
||||||
|
|
||||||
## Non-negotiables
|
## Non-negotiables
|
||||||
- **Clean-room.** Fusion may be *observed* black-box (its UI, its toolbar dump, parts built in it
|
- **Independent.** SolidCraft is independent. Behaviour is designed from public documentation,
|
||||||
and their measurements, kept under `plan/fusion/`, never committed). Never copy Autodesk icons,
|
general CAD conventions and user feedback. Reference tests use analytic values and open-source
|
||||||
artwork, help text, tooltips, templates or materials, and never commit files produced by
|
tools. Never copy another product's code, icons, artwork, help text, tooltips, templates or
|
||||||
Fusion. Command ids and command names are used as identifiers only (`xtask/data/fusion-catalog.tsv`
|
materials. File formats come from public specifications.
|
||||||
holds ids and names, nothing else). File formats come from public specifications. **Never read,
|
- **No commercial CAD products.** Agents must not drive, script, automate or extract data from
|
||||||
copy or link GPL/LGPL/AGPL code**: OpenCASCADE, FreeCAD (incl. planegcs), SolveSpace,
|
commercial CAD products (Fusion, SolidWorks, Onshape, …) for this project: no test data,
|
||||||
CadQuery/OCP, LibreCAD, QCAD — don't even read their sources. (`tools/freecad-oracle/` runs
|
measurements, command lists, ids or files produced with them.
|
||||||
FreeCAD as a separate program through its public scripting API to compute reference values;
|
- **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
|
nothing from FreeCAD is linked, vendored or shipped.) The sketch solver and the blend
|
||||||
operations are our own.
|
operations are our own.
|
||||||
- **Assets — absolutely essential.** SolidCraft contains **no Autodesk iconography, images,
|
- **Assets — absolutely essential.** SolidCraft contains **no iconography, images, fonts or
|
||||||
fonts or artwork — ever.** Every icon is drawn in code (`crates/ui-egui/src/icons.rs`). Any
|
artwork from commercial CAD products — ever.** Every icon is drawn in code
|
||||||
file asset must be original or openly licensed and **must have a row in ATTRIBUTION.md**
|
(`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.
|
(`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.
|
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/*`
|
- **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
|
(`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`.
|
`solvecraft-cli snapshot script.json --out shot.png`, `solvecraft-cli commands`.
|
||||||
- Reference tests: `cargo xtask oracle` replays `tests/oracle/*/recipe.json` and compares with
|
- 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
|
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`.
|
- Build with `CARGO_TARGET_DIR=<repo>/target`. Windows: `cargo xwin build --release --target x86_64-pc-windows-msvc -p solvecraft`.
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
`ROADMAP.md` (committed) tracks status, milestones, parity and estimates. Update it whenever a
|
`ROADMAP.md` (committed) tracks status, milestones and estimates. Update it whenever a
|
||||||
milestone task lands. `cargo xtask parity` recomputes command parity in `docs/parity.md`;
|
milestone task lands. `cargo xtask features` regenerates `docs/features.md` (SolidCraft's
|
||||||
`cargo xtask oracle` recomputes `docs/oracle.md`.
|
commands by area, from the registry) when commands are added or renamed.
|
||||||
@@ -16,8 +16,7 @@ compatibility notes.
|
|||||||
|
|
||||||
## Start every session here
|
## Start every session here
|
||||||
1. Read `plan/STATUS.md` (current milestone, next task), then the task in `plan/execution-plan.md`
|
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/`
|
and the relevant `plan/architecture.md` section.
|
||||||
(`menu-tree.json` is Fusion's toolbar dump).
|
|
||||||
2. Kernel and library decisions: `plan/adr/0001-geometry-kernel.md` (what we may depend on, what
|
2. Kernel and library decisions: `plan/adr/0001-geometry-kernel.md` (what we may depend on, what
|
||||||
is rejected for licence reasons).
|
is rejected for licence reasons).
|
||||||
3. Follow the autonomous operation protocol (`plan/execution-plan.md` §6). Don't stop to ask
|
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)]`.
|
`#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]`.
|
||||||
|
|
||||||
## Non-negotiables
|
## Non-negotiables
|
||||||
- **Clean-room.** Fusion may be *observed* black-box (its UI, its toolbar dump, parts built in it
|
- **Independent.** SolidCraft is independent. Behaviour is designed from public documentation,
|
||||||
and their measurements, kept under `plan/fusion/`, never committed). Never copy Autodesk icons,
|
general CAD conventions and user feedback. Reference tests use analytic values and open-source
|
||||||
artwork, help text, tooltips, templates or materials, and never commit files produced by
|
tools. Never copy another product's code, icons, artwork, help text, tooltips, templates or
|
||||||
Fusion. Command ids and command names are used as identifiers only (`xtask/data/fusion-catalog.tsv`
|
materials. File formats come from public specifications.
|
||||||
holds ids and names, nothing else). File formats come from public specifications. **Never read,
|
- **No commercial CAD products.** Agents must not drive, script, automate or extract data from
|
||||||
copy or link GPL/LGPL/AGPL code**: OpenCASCADE, FreeCAD (incl. planegcs), SolveSpace,
|
commercial CAD products (Fusion, SolidWorks, Onshape, …) for this project: no test data,
|
||||||
CadQuery/OCP, LibreCAD, QCAD — don't even read their sources. (`tools/freecad-oracle/` runs
|
measurements, command lists, ids or files produced with them.
|
||||||
FreeCAD as a separate program through its public scripting API to compute reference values;
|
- **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
|
nothing from FreeCAD is linked, vendored or shipped.) The sketch solver and the blend
|
||||||
operations are our own.
|
operations are our own.
|
||||||
- **Assets — absolutely essential.** SolidCraft contains **no Autodesk iconography, images,
|
- **Assets — absolutely essential.** SolidCraft contains **no iconography, images, fonts or
|
||||||
fonts or artwork — ever.** Every icon is drawn in code (`crates/ui-egui/src/icons.rs`). Any
|
artwork from commercial CAD products — ever.** Every icon is drawn in code
|
||||||
file asset must be original or openly licensed and **must have a row in ATTRIBUTION.md**
|
(`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.
|
(`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.
|
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/*`
|
- **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
|
(`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`.
|
`solvecraft-cli snapshot script.json --out shot.png`, `solvecraft-cli commands`.
|
||||||
- Reference tests: `cargo xtask oracle` replays `tests/oracle/*/recipe.json` and compares with
|
- 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
|
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`.
|
- Build with `CARGO_TARGET_DIR=<repo>/target`. Windows: `cargo xwin build --release --target x86_64-pc-windows-msvc -p solvecraft`.
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
`ROADMAP.md` (committed) tracks status, milestones, parity and estimates. Update it whenever a
|
`ROADMAP.md` (committed) tracks status, milestones and estimates. Update it whenever a
|
||||||
milestone task lands. `cargo xtask parity` recomputes command parity in `docs/parity.md`;
|
milestone task lands. `cargo xtask features` regenerates `docs/features.md` (SolidCraft's
|
||||||
`cargo xtask oracle` recomputes `docs/oracle.md`.
|
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
|
## Rules that aren't negotiable
|
||||||
|
|
||||||
1. **Clean-room.** We observe Fusion as a black box: its UI, how parts it builds measure, and
|
1. **Independent.** SolidCraft is independent. Behaviour is designed from public
|
||||||
what it does with a given input. We never copy Autodesk code, icons, artwork, help text,
|
documentation, general CAD conventions and user feedback. Reference tests use analytic values
|
||||||
tooltips, templates or materials, and we never commit files Fusion produced. Command ids are
|
and open-source tools. We don't drive, script, automate or extract data from commercial CAD
|
||||||
our own (`solid.fillet`, not Fusion's internal names).
|
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
|
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
|
(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
|
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).
|
`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
|
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
|
**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
|
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.
|
([docs/oracle.md](docs/oracle.md)); the other is a tracked bug.
|
||||||
These checks do not establish complete geometric or workflow equivalence. Feature coverage
|
These checks do not establish complete geometric or workflow equivalence. The commands SolidCraft has
|
||||||
is tracked in [docs/parity.md](docs/parity.md) and [ROADMAP.md](ROADMAP.md).
|
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),
|
Open work and known bugs are in [GitHub issues](https://github.com/bherbruck/solidcraft/issues),
|
||||||
and help is welcome: see [CONTRIBUTING.md](CONTRIBUTING.md).
|
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
|
[clean-room contribution rules](CLAUDE.md); third-party code and assets retain their
|
||||||
documented licences and attribution.
|
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
|
SolidCraft is not affiliated with, sponsored by or endorsed by Autodesk. Autodesk and
|
||||||
Fusion are trademarks of Autodesk, Inc.
|
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 |
|
| 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. |
|
| 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. |
|
||||||
| 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 |
|
| 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). |
|
| 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. |
|
| 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 |
|
| 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
|
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,
|
designs, interactive angle placement, file-picker sketch imports, Home/recent controls,
|
||||||
toolbar overflow, and the remaining component-frame and assembly WIP work. The enclosure
|
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
|
acceptance scenarios now include board resizes; STEP reopening is automated. See [WIP reconciliation](docs/wip-reconciliation.md).
|
||||||
Fusion remains an external acceptance step. See [WIP reconciliation](docs/wip-reconciliation.md).
|
|
||||||
|
|
||||||
In scope, in priority order:
|
In scope, in priority order:
|
||||||
1. SOLID and SKETCH (now).
|
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.
|
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
|
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
|
PCB / Package, Render, Animation, Simulation, Manufacture/CAM, Drawings.
|
||||||
headline counts in-scope tabs only and lists the deferred ones separately.
|
|
||||||
|
|
||||||
## Milestones
|
## 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 |
|
| 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 |
|
| 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 |
|
| 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), 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 |
|
|
||||||
| 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 |
|
| 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 |
|
| 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 |
|
| 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 | — |
|
| 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 |
|
| 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 | — |
|
| 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 |
|
| 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 |
|
| 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
|
- Rolling-ball fillet accuracy: independent offset-cylinder tee references check surface
|
||||||
distance, actual trimmed tessellation, supporting-cylinder contacts and tangency at two
|
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
|
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,
|
- Contact driving checks the trajectory between clear endpoints, including linked joints,
|
||||||
playback and sparse motion exports. Checks use bounded tessellation samples, not exact
|
playback and sparse motion exports. Checks use bounded tessellation samples, not exact
|
||||||
continuous collision detection; local thin walls and small details remain limitations.
|
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};
|
use crate::{Result, Session};
|
||||||
|
|
||||||
pub static COMMANDS: &[CommandSpec] = &[
|
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",
|
"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(
|
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> {
|
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 tools = string_list(p, "tools");
|
||||||
let st = s.model.state();
|
let st = s.model.state();
|
||||||
if tools.is_empty() || tools.len() > 64 || tools.iter().any(|t| st.body(t).is_none()) {
|
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`,
|
//! The command registry. Ids are SolveCraft's own dotted ids (`solid.extrude`,
|
||||||
//! `sketch.rectangle.two_point`); the toolbar placement (`tab`, `panel`) follows the familiar
|
//! `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`).
|
/// The params-doc note of every command that adds sketch geometry (see `sketch::created`).
|
||||||
macro_rules! created_doc {
|
macro_rules! created_doc {
|
||||||
@@ -180,7 +180,5 @@ pub fn command_specs() -> Vec<&'static CommandSpec> {
|
|||||||
|
|
||||||
pub fn find_command(id: &str) -> Option<&'static CommandSpec> {
|
pub fn find_command(id: &str) -> Option<&'static CommandSpec> {
|
||||||
let all = command_specs();
|
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()
|
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.line", json!({"points": pts})),
|
||||||
("sketch.arc.three_point", json!({"start": [0, h], "end": [0, 0], "through": [-bulge, h / 2.0]})),
|
("sketch.arc.three_point", json!({"start": [0, h], "end": [0, 0], "through": [-bulge, h / 2.0]})),
|
||||||
("sketch.finish", json!({})),
|
("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.create", json!({"plane": "XZ"})),
|
||||||
("sketch.rectangle.two_point", json!({"p0": [r0, 0], "p1": [r1, h]})),
|
("sketch.rectangle.two_point", json!({"p0": [r0, 0], "p1": [r1, h]})),
|
||||||
("sketch.finish", json!({})),
|
("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 cmd;
|
||||||
pub mod frames;
|
pub mod frames;
|
||||||
pub mod fuzz;
|
pub mod fuzz;
|
||||||
pub mod legacy_ids;
|
|
||||||
pub mod licences;
|
pub mod licences;
|
||||||
pub mod occurrences;
|
pub mod occurrences;
|
||||||
pub mod params;
|
pub mod params;
|
||||||
|
|||||||
@@ -512,11 +512,22 @@ fn registry_is_consistent() {
|
|||||||
let n = ids.len();
|
let n = ids.len();
|
||||||
ids.dedup();
|
ids.dedup();
|
||||||
assert_eq!(ids.len(), n, "duplicate command ids");
|
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();
|
let s = Session::default();
|
||||||
assert!(!find_command("sketch.line").unwrap().info(&s).enabled);
|
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]
|
#[test]
|
||||||
fn sample_design_builds() {
|
fn sample_design_builds() {
|
||||||
let mut s = Session::default();
|
let mut s = Session::default();
|
||||||
@@ -2336,15 +2347,15 @@ fn boundary_fill_cells() {
|
|||||||
let mut s = Session::default();
|
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!({"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"}));
|
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!({}));
|
let m = run(&mut s, "inspect.measure", json!({}));
|
||||||
assert_eq!(m["body_count"], 1, "{r} {m}");
|
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);
|
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, "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!({}));
|
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!(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
|
/// Rectangles name their sides and corners, so they can be dimensioned without inspecting the
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ impl Dialog {
|
|||||||
Kind::ReplaceFace,
|
Kind::ReplaceFace,
|
||||||
vec![SelInput::new("Faces", PLANAR_FACES, true), SelInput::new("Target", PLANES | PLANAR_FACES, false)],
|
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)])
|
Dialog::new(Kind::BoundaryFill { operation: 0, cells: Vec::new(), of: Vec::new() }, vec![SelInput::new("Tools", BODIES, true)])
|
||||||
}
|
}
|
||||||
"solid.align" => Dialog::new(
|
"solid.align" => Dialog::new(
|
||||||
@@ -2848,7 +2848,7 @@ fn dialog_commands(app: &SolveApp, d: &Dialog) -> Result<Vec<(String, Value)>, S
|
|||||||
if picked.is_empty() {
|
if picked.is_empty() {
|
||||||
return Err("tick the cells to fill".into());
|
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 } => {
|
Kind::Combine { operation, keep_tools } => {
|
||||||
need(0, "the target body")?;
|
need(0, "the target body")?;
|
||||||
@@ -3383,7 +3383,7 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
|||||||
d
|
d
|
||||||
}
|
}
|
||||||
FeatureKind::BoundaryFill { tools, cells, operation, remove_tools } => {
|
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.
|
// The cells again, ticked where a stored cell point lies in the same cell.
|
||||||
let before = s.model.state_before(f.id);
|
let before = s.model.state_before(f.id);
|
||||||
let found = fill_cells(&before, tools);
|
let found = fill_cells(&before, tools);
|
||||||
|
|||||||
@@ -38,15 +38,10 @@ impl Keymap {
|
|||||||
}
|
}
|
||||||
pub fn load(&mut self, v: &Value) {
|
pub fn load(&mut self, v: &Value) {
|
||||||
self.custom =
|
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`.
|
/// 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 {
|
pub fn key_name(key: egui::Key, mods: egui::Modifiers) -> String {
|
||||||
let mut s = String::new();
|
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);
|
tc::reorder(&mut app, "SOLID", extra, "MODIFY", None);
|
||||||
assert!(!ids(&app, "CREATE").contains(&extra) && ids(&app, "MODIFY").last() == Some(&extra));
|
assert!(!ids(&app, "CREATE").contains(&extra) && ids(&app, "MODIFY").last() == Some(&extra));
|
||||||
// Pin to Shortcuts goes to the S box's favourites.
|
// Pin to Shortcuts goes to the S box's favourites.
|
||||||
act(&mut app, &Target::ToolbarCommand { id: "Extrude".into() }, "Pin to Shortcuts");
|
act(&mut app, &Target::ToolbarCommand { id: "solid.extrude".into() }, "Pin to Shortcuts");
|
||||||
assert!(app.sbox.pinned.iter().any(|p| p == "Extrude"));
|
assert!(app.sbox.pinned.iter().any(|p| p == "solid.extrude"));
|
||||||
// Kept between runs, and exported and imported with the shortcuts.
|
// Kept between runs, and exported and imported with the shortcuts.
|
||||||
let mut other = sample_app();
|
let mut other = sample_app();
|
||||||
other.load_prefs(&app.prefs());
|
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}},
|
||||||
{"command": "solid.box", "params": {"length": 20, "width": 20, "height": 20, "corner": [10, 10, 0], "operation": "new"}}
|
{"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() }];
|
d.inputs[0].items = vec![Sel::Body { name: "Body1".into() }, Sel::Body { name: "Body2".into() }];
|
||||||
app.dialog = Some(d);
|
app.dialog = Some(d);
|
||||||
// The dialog finds the cells on its next frame.
|
// The dialog finds the cells on its next frame.
|
||||||
|
|||||||
@@ -34,10 +34,7 @@ impl ShortcutBox {
|
|||||||
}
|
}
|
||||||
pub fn load(&mut self, v: &Value) {
|
pub fn load(&mut self, v: &Value) {
|
||||||
let list = |k: &str| -> Vec<String> {
|
let list = |k: &str| -> Vec<String> {
|
||||||
v.get(k)
|
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()
|
||||||
.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()
|
|
||||||
};
|
};
|
||||||
self.recent = list("recent");
|
self.recent = list("recent");
|
||||||
self.pinned = list("pinned");
|
self.pinned = list("pinned");
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
- [Test harnesses](dev/testing.md)
|
- [Test harnesses](dev/testing.md)
|
||||||
- [Control protocol](dev/control-protocol.md)
|
- [Control protocol](dev/control-protocol.md)
|
||||||
- [Reference tests](dev/oracle.md)
|
- [Reference tests](dev/oracle.md)
|
||||||
- [Command parity](dev/parity.md)
|
- [Features](dev/features.md)
|
||||||
- [STEP import](dev/step-import.md)
|
- [STEP import](dev/step-import.md)
|
||||||
|
|
||||||
# Reference
|
# 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
|
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`,
|
[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:
|
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
|
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.
|
(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
|
Only the registry's own dotted ids name commands (matched ignoring case); any other id fails
|
||||||
old scripts, recipes, saved shortcuts and toolbar layouts keep working.
|
with `unknown command`.
|
||||||
|
|
||||||
## Adding a 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.
|
clearance per material, used as the features' defaults.
|
||||||
|
|
||||||
Rib and web (on the SOLID tab) complete the set. These features are checked against
|
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
|
- **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.
|
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
|
Bends follow the rule's K-factor, so flat lengths match what a press brake will make. Tests
|
||||||
oracle checks these against parts built in Fusion.
|
check flat lengths against hand-computed bend allowances.
|
||||||
|
|
||||||
For a shop drawing or spreadsheet, `sheet.export_bend_table` returns CSV by default; choose
|
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,
|
`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
|
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
|
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
|
[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
|
the [feature list](dev/features.md) lists every command by area, and the
|
||||||
is.
|
[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.
|
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
|
**developer guide** for people working on it. The [command reference](reference/commands.md) is
|
||||||
generated from the code on every build.
|
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
|
SolidCraft is licensed MIT OR Apache-2.0. It is independent: behaviour is designed from public
|
||||||
with Autodesk; Fusion is a trademark of Autodesk, Inc.
|
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)
|
# WIP branch reconciliation (#6)
|
||||||
|
|
||||||
The branches predate the dotted command IDs. Their remaining changes were ported through
|
The branches predate the dotted command IDs. Their remaining changes were ported to the
|
||||||
`crates/engine/src/legacy_ids.rs` and reconciled with the current implementation.
|
dotted ids and reconciled with the current implementation.
|
||||||
|
|
||||||
| Branches | Result |
|
| 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 assets;
|
||||||
mod book;
|
mod book;
|
||||||
|
mod features;
|
||||||
mod layers;
|
mod layers;
|
||||||
mod licences;
|
mod licences;
|
||||||
mod parity;
|
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@@ -19,9 +19,7 @@ usage: cargo xtask <command>
|
|||||||
commands:
|
commands:
|
||||||
layers enforce the crate dependency layering (plan/architecture.md §3)
|
layers enforce the crate dependency layering (plan/architecture.md §3)
|
||||||
assets check that every non-code asset file is attributed in ATTRIBUTION.md
|
assets check that every non-code asset file is attributed in ATTRIBUTION.md
|
||||||
parity [--refresh]
|
features list SolidCraft's commands by area in docs/features.md (from the registry)
|
||||||
recompute Fusion command parity in docs/parity.md (--refresh rebuilds
|
|
||||||
xtask/data/fusion-catalog.tsv from plan/fusion/menu-tree.json)
|
|
||||||
oracle [--cli BIN]
|
oracle [--cli BIN]
|
||||||
replay the reference tests (tests/oracle/*/recipe.json), compare with each
|
replay the reference tests (tests/oracle/*/recipe.json), compare with each
|
||||||
case's expected.json and write docs/oracle.md (--cli: a solvecraft-cli
|
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) {
|
let result = match args.first().map(String::as_str) {
|
||||||
Some("layers") => cmd_layers(),
|
Some("layers") => cmd_layers(),
|
||||||
Some("assets") => assets::run(&root()),
|
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("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("book") => book::run(&root(), !rest.contains(&"--no-build")),
|
||||||
Some("licences") => licences::run(&root(), rest.contains(&"--check")),
|
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