From eb2fc986a40eeb55635e1cd7a22ab15284903e56 Mon Sep 17 00:00:00 2001 From: Tommaso Bianchi Date: Fri, 31 Jul 2026 11:40:45 +0200 Subject: [PATCH] =?UTF-8?q?docs/ux:=20the=20offer=20atlas=20=E2=80=94=20ev?= =?UTF-8?q?ery=20tool,=20every=20state,=20drawn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The charter fixed the slot-constancy invariant but carried one hand-written eight-cell table as an illustration, and nothing of the offer exists in the product. Before any GUI code, the group needs the map itself: what verbs there are, what each one needs before it can be offered, and what the ring actually looks like in every situation a user can put it in. tool_atlas.json is the source of truth and it was extracted from the code, not from memory: verbs, shortcuts and the exact refusal strings from DesignPanel's six feat_dropdown call sites and the sk_key table, kernel coverage checked against CadFeatureType, headless coverage against McpControl's dispatch, and the selection kinds taken from the callbacks DesignCanvas actually exposes. It carries each verb's preconditions, so "why is that slot empty" has an answer already written in the product's own words. The eventual C++ table generates from this file too — the map exists once. gen_offer_mockups.py renders it: 20 selection kinds x 2 document states = 40 primary rings, plus 73 sub-rings, plus comparison sheets. 113 states, none of them hand-drawn, because a human drawing 113 rings is exactly how an address quietly changes. Everything is framed at 1366x768, the charter's own reach target, so L11 is tested in the mockups before it is tested in code. Three things the drawing found that the prose had not: - MEAN FILL IS 3.45 OF 8. The empty-slot rule is cheap in argument and expensive on screen; on a fresh document exactly two slots are live. That picture is the anti-clutter thesis made literal and it is the strongest image in the set. - SUB-RINGS MUST ANCHOR ON THEIR PARENT. Fanning them from north put Extrude at N, which is Create's address in the primary map, so the second level contradicted the first. Anchored, an address is two consistent strokes: Add material is NE and its first verb is NE again. - ONE FAMILY OVERFLOWS, AND ONLY ONE. Sketch-mode Create needs nine addresses on an eight-slot ring. That is the ninth-position pressure the charter predicted, arriving on schedule and measured rather than argued: either Point moves family, or the tail goes to a third level, or the ring is not eight. Every model-mode family fits. The generator refuses to wrap a tenth verb onto a first — silent collision is the one outcome worse than an ugly ring — and reports the overflow instead. Also fixed while looking at renders: the selection pill sat on top of the north slot's shortcut chip and hid it, and the scrim at 0.55 swallowed the very face the ring had been opened on, which is 4.1 failing inside its own mockup. Fork-neutral: the generator and everything it emits name no product, so both forks carry byte-identical copies. snaporca-2is. --- docs/ux/mockups/cmp_12__edge_str.svg | 1 + docs/ux/mockups/cmp_12__face_planar.svg | 1 + docs/ux/mockups/cmp_12__sk_line.svg | 1 + docs/ux/mockups/cmp_8__edge_str.svg | 1 + docs/ux/mockups/cmp_8__face_planar.svg | 1 + docs/ux/mockups/cmp_8__sk_line.svg | 1 + docs/ux/mockups/fresh__art.svg | 1 + docs/ux/mockups/fresh__art__modify.svg | 1 + docs/ux/mockups/fresh__bodies_2.svg | 1 + docs/ux/mockups/fresh__body_sheet.svg | 1 + docs/ux/mockups/fresh__body_sheet__modify.svg | 1 + docs/ux/mockups/fresh__body_solid.svg | 1 + docs/ux/mockups/fresh__body_solid__modify.svg | 1 + docs/ux/mockups/fresh__coordsys.svg | 1 + docs/ux/mockups/fresh__coordsys__modify.svg | 1 + docs/ux/mockups/fresh__datum_axis.svg | 1 + docs/ux/mockups/fresh__datum_axis__modify.svg | 1 + docs/ux/mockups/fresh__datum_plane.svg | 1 + .../ux/mockups/fresh__datum_plane__modify.svg | 1 + .../mockups/fresh__datum_plane__reference.svg | 1 + docs/ux/mockups/fresh__edge_circ.svg | 1 + docs/ux/mockups/fresh__edge_str.svg | 1 + .../ux/mockups/fresh__edge_str__reference.svg | 1 + docs/ux/mockups/fresh__face_cyl.svg | 1 + .../ux/mockups/fresh__face_cyl__reference.svg | 1 + docs/ux/mockups/fresh__face_other.svg | 1 + docs/ux/mockups/fresh__face_planar.svg | 1 + .../mockups/fresh__face_planar__reference.svg | 1 + docs/ux/mockups/fresh__none.svg | 1 + docs/ux/mockups/fresh__none__reference.svg | 1 + docs/ux/mockups/fresh__sk_2ent.svg | 1 + docs/ux/mockups/fresh__sk_2ent__create.svg | 1 + docs/ux/mockups/fresh__sk_2ent__dressup.svg | 1 + docs/ux/mockups/fresh__sk_2ent__modify.svg | 1 + docs/ux/mockups/fresh__sk_2ent__reference.svg | 1 + docs/ux/mockups/fresh__sk_arc.svg | 1 + docs/ux/mockups/fresh__sk_arc__create.svg | 1 + docs/ux/mockups/fresh__sk_arc__modify.svg | 1 + docs/ux/mockups/fresh__sk_arc__reference.svg | 1 + docs/ux/mockups/fresh__sk_line.svg | 1 + docs/ux/mockups/fresh__sk_line__create.svg | 1 + docs/ux/mockups/fresh__sk_line__dressup.svg | 1 + docs/ux/mockups/fresh__sk_line__modify.svg | 1 + docs/ux/mockups/fresh__sk_line__reference.svg | 1 + docs/ux/mockups/fresh__sk_loop.svg | 1 + docs/ux/mockups/fresh__sk_loop__add.svg | 1 + docs/ux/mockups/fresh__sk_loop__modify.svg | 1 + docs/ux/mockups/fresh__sk_none.svg | 1 + docs/ux/mockups/fresh__sk_none__create.svg | 1 + docs/ux/mockups/fresh__sk_none__reference.svg | 1 + docs/ux/mockups/fresh__sk_point.svg | 1 + docs/ux/mockups/fresh__sk_point__create.svg | 1 + .../ux/mockups/fresh__sk_point__reference.svg | 1 + docs/ux/mockups/fresh__vertex.svg | 1 + docs/ux/mockups/fresh__vertex__reference.svg | 1 + docs/ux/mockups/gen_offer_mockups.py | 736 ++++++++++++++++++ docs/ux/mockups/rich__art.svg | 1 + docs/ux/mockups/rich__art__modify.svg | 1 + docs/ux/mockups/rich__bodies_2.svg | 1 + docs/ux/mockups/rich__bodies_2__reference.svg | 1 + docs/ux/mockups/rich__body_sheet.svg | 1 + docs/ux/mockups/rich__body_sheet__modify.svg | 1 + docs/ux/mockups/rich__body_solid.svg | 1 + docs/ux/mockups/rich__body_solid__dressup.svg | 1 + docs/ux/mockups/rich__body_solid__modify.svg | 1 + .../mockups/rich__body_solid__reference.svg | 1 + docs/ux/mockups/rich__body_solid__remove.svg | 1 + docs/ux/mockups/rich__body_solid__repeat.svg | 1 + docs/ux/mockups/rich__coordsys.svg | 1 + docs/ux/mockups/rich__coordsys__modify.svg | 1 + docs/ux/mockups/rich__datum_axis.svg | 1 + docs/ux/mockups/rich__datum_axis__modify.svg | 1 + docs/ux/mockups/rich__datum_plane.svg | 1 + docs/ux/mockups/rich__datum_plane__modify.svg | 1 + .../mockups/rich__datum_plane__reference.svg | 1 + docs/ux/mockups/rich__datum_plane__remove.svg | 1 + docs/ux/mockups/rich__edge_circ.svg | 1 + docs/ux/mockups/rich__edge_circ__dressup.svg | 1 + docs/ux/mockups/rich__edge_str.svg | 1 + docs/ux/mockups/rich__edge_str__dressup.svg | 1 + docs/ux/mockups/rich__edge_str__reference.svg | 1 + docs/ux/mockups/rich__face_cyl.svg | 1 + docs/ux/mockups/rich__face_cyl__modify.svg | 1 + docs/ux/mockups/rich__face_cyl__reference.svg | 1 + docs/ux/mockups/rich__face_other.svg | 1 + docs/ux/mockups/rich__face_other__modify.svg | 1 + docs/ux/mockups/rich__face_planar.svg | 1 + docs/ux/mockups/rich__face_planar__add.svg | 1 + .../ux/mockups/rich__face_planar__dressup.svg | 1 + docs/ux/mockups/rich__face_planar__modify.svg | 1 + .../mockups/rich__face_planar__reference.svg | 1 + docs/ux/mockups/rich__face_planar__remove.svg | 1 + .../mockups/rich__face_planar__transform.svg | 1 + docs/ux/mockups/rich__none.svg | 1 + docs/ux/mockups/rich__none__reference.svg | 1 + docs/ux/mockups/rich__sk_2ent.svg | 1 + docs/ux/mockups/rich__sk_2ent__create.svg | 1 + docs/ux/mockups/rich__sk_2ent__dressup.svg | 1 + docs/ux/mockups/rich__sk_2ent__modify.svg | 1 + docs/ux/mockups/rich__sk_2ent__reference.svg | 1 + docs/ux/mockups/rich__sk_arc.svg | 1 + docs/ux/mockups/rich__sk_arc__create.svg | 1 + docs/ux/mockups/rich__sk_arc__modify.svg | 1 + docs/ux/mockups/rich__sk_arc__reference.svg | 1 + docs/ux/mockups/rich__sk_line.svg | 1 + docs/ux/mockups/rich__sk_line__create.svg | 1 + docs/ux/mockups/rich__sk_line__dressup.svg | 1 + docs/ux/mockups/rich__sk_line__modify.svg | 1 + docs/ux/mockups/rich__sk_line__reference.svg | 1 + docs/ux/mockups/rich__sk_loop.svg | 1 + docs/ux/mockups/rich__sk_loop__add.svg | 1 + docs/ux/mockups/rich__sk_loop__modify.svg | 1 + docs/ux/mockups/rich__sk_none.svg | 1 + docs/ux/mockups/rich__sk_none__create.svg | 1 + docs/ux/mockups/rich__sk_none__reference.svg | 1 + docs/ux/mockups/rich__sk_point.svg | 1 + docs/ux/mockups/rich__sk_point__create.svg | 1 + docs/ux/mockups/rich__sk_point__reference.svg | 1 + docs/ux/mockups/rich__vertex.svg | 1 + docs/ux/mockups/rich__vertex__reference.svg | 1 + docs/ux/offer_atlas.html | 68 ++ docs/ux/offer_atlas_inline.html | 67 ++ docs/ux/tool_atlas.json | 220 ++++++ 123 files changed, 1210 insertions(+) create mode 100644 docs/ux/mockups/cmp_12__edge_str.svg create mode 100644 docs/ux/mockups/cmp_12__face_planar.svg create mode 100644 docs/ux/mockups/cmp_12__sk_line.svg create mode 100644 docs/ux/mockups/cmp_8__edge_str.svg create mode 100644 docs/ux/mockups/cmp_8__face_planar.svg create mode 100644 docs/ux/mockups/cmp_8__sk_line.svg create mode 100644 docs/ux/mockups/fresh__art.svg create mode 100644 docs/ux/mockups/fresh__art__modify.svg create mode 100644 docs/ux/mockups/fresh__bodies_2.svg create mode 100644 docs/ux/mockups/fresh__body_sheet.svg create mode 100644 docs/ux/mockups/fresh__body_sheet__modify.svg create mode 100644 docs/ux/mockups/fresh__body_solid.svg create mode 100644 docs/ux/mockups/fresh__body_solid__modify.svg create mode 100644 docs/ux/mockups/fresh__coordsys.svg create mode 100644 docs/ux/mockups/fresh__coordsys__modify.svg create mode 100644 docs/ux/mockups/fresh__datum_axis.svg create mode 100644 docs/ux/mockups/fresh__datum_axis__modify.svg create mode 100644 docs/ux/mockups/fresh__datum_plane.svg create mode 100644 docs/ux/mockups/fresh__datum_plane__modify.svg create mode 100644 docs/ux/mockups/fresh__datum_plane__reference.svg create mode 100644 docs/ux/mockups/fresh__edge_circ.svg create mode 100644 docs/ux/mockups/fresh__edge_str.svg create mode 100644 docs/ux/mockups/fresh__edge_str__reference.svg create mode 100644 docs/ux/mockups/fresh__face_cyl.svg create mode 100644 docs/ux/mockups/fresh__face_cyl__reference.svg create mode 100644 docs/ux/mockups/fresh__face_other.svg create mode 100644 docs/ux/mockups/fresh__face_planar.svg create mode 100644 docs/ux/mockups/fresh__face_planar__reference.svg create mode 100644 docs/ux/mockups/fresh__none.svg create mode 100644 docs/ux/mockups/fresh__none__reference.svg create mode 100644 docs/ux/mockups/fresh__sk_2ent.svg create mode 100644 docs/ux/mockups/fresh__sk_2ent__create.svg create mode 100644 docs/ux/mockups/fresh__sk_2ent__dressup.svg create mode 100644 docs/ux/mockups/fresh__sk_2ent__modify.svg create mode 100644 docs/ux/mockups/fresh__sk_2ent__reference.svg create mode 100644 docs/ux/mockups/fresh__sk_arc.svg create mode 100644 docs/ux/mockups/fresh__sk_arc__create.svg create mode 100644 docs/ux/mockups/fresh__sk_arc__modify.svg create mode 100644 docs/ux/mockups/fresh__sk_arc__reference.svg create mode 100644 docs/ux/mockups/fresh__sk_line.svg create mode 100644 docs/ux/mockups/fresh__sk_line__create.svg create mode 100644 docs/ux/mockups/fresh__sk_line__dressup.svg create mode 100644 docs/ux/mockups/fresh__sk_line__modify.svg create mode 100644 docs/ux/mockups/fresh__sk_line__reference.svg create mode 100644 docs/ux/mockups/fresh__sk_loop.svg create mode 100644 docs/ux/mockups/fresh__sk_loop__add.svg create mode 100644 docs/ux/mockups/fresh__sk_loop__modify.svg create mode 100644 docs/ux/mockups/fresh__sk_none.svg create mode 100644 docs/ux/mockups/fresh__sk_none__create.svg create mode 100644 docs/ux/mockups/fresh__sk_none__reference.svg create mode 100644 docs/ux/mockups/fresh__sk_point.svg create mode 100644 docs/ux/mockups/fresh__sk_point__create.svg create mode 100644 docs/ux/mockups/fresh__sk_point__reference.svg create mode 100644 docs/ux/mockups/fresh__vertex.svg create mode 100644 docs/ux/mockups/fresh__vertex__reference.svg create mode 100644 docs/ux/mockups/gen_offer_mockups.py create mode 100644 docs/ux/mockups/rich__art.svg create mode 100644 docs/ux/mockups/rich__art__modify.svg create mode 100644 docs/ux/mockups/rich__bodies_2.svg create mode 100644 docs/ux/mockups/rich__bodies_2__reference.svg create mode 100644 docs/ux/mockups/rich__body_sheet.svg create mode 100644 docs/ux/mockups/rich__body_sheet__modify.svg create mode 100644 docs/ux/mockups/rich__body_solid.svg create mode 100644 docs/ux/mockups/rich__body_solid__dressup.svg create mode 100644 docs/ux/mockups/rich__body_solid__modify.svg create mode 100644 docs/ux/mockups/rich__body_solid__reference.svg create mode 100644 docs/ux/mockups/rich__body_solid__remove.svg create mode 100644 docs/ux/mockups/rich__body_solid__repeat.svg create mode 100644 docs/ux/mockups/rich__coordsys.svg create mode 100644 docs/ux/mockups/rich__coordsys__modify.svg create mode 100644 docs/ux/mockups/rich__datum_axis.svg create mode 100644 docs/ux/mockups/rich__datum_axis__modify.svg create mode 100644 docs/ux/mockups/rich__datum_plane.svg create mode 100644 docs/ux/mockups/rich__datum_plane__modify.svg create mode 100644 docs/ux/mockups/rich__datum_plane__reference.svg create mode 100644 docs/ux/mockups/rich__datum_plane__remove.svg create mode 100644 docs/ux/mockups/rich__edge_circ.svg create mode 100644 docs/ux/mockups/rich__edge_circ__dressup.svg create mode 100644 docs/ux/mockups/rich__edge_str.svg create mode 100644 docs/ux/mockups/rich__edge_str__dressup.svg create mode 100644 docs/ux/mockups/rich__edge_str__reference.svg create mode 100644 docs/ux/mockups/rich__face_cyl.svg create mode 100644 docs/ux/mockups/rich__face_cyl__modify.svg create mode 100644 docs/ux/mockups/rich__face_cyl__reference.svg create mode 100644 docs/ux/mockups/rich__face_other.svg create mode 100644 docs/ux/mockups/rich__face_other__modify.svg create mode 100644 docs/ux/mockups/rich__face_planar.svg create mode 100644 docs/ux/mockups/rich__face_planar__add.svg create mode 100644 docs/ux/mockups/rich__face_planar__dressup.svg create mode 100644 docs/ux/mockups/rich__face_planar__modify.svg create mode 100644 docs/ux/mockups/rich__face_planar__reference.svg create mode 100644 docs/ux/mockups/rich__face_planar__remove.svg create mode 100644 docs/ux/mockups/rich__face_planar__transform.svg create mode 100644 docs/ux/mockups/rich__none.svg create mode 100644 docs/ux/mockups/rich__none__reference.svg create mode 100644 docs/ux/mockups/rich__sk_2ent.svg create mode 100644 docs/ux/mockups/rich__sk_2ent__create.svg create mode 100644 docs/ux/mockups/rich__sk_2ent__dressup.svg create mode 100644 docs/ux/mockups/rich__sk_2ent__modify.svg create mode 100644 docs/ux/mockups/rich__sk_2ent__reference.svg create mode 100644 docs/ux/mockups/rich__sk_arc.svg create mode 100644 docs/ux/mockups/rich__sk_arc__create.svg create mode 100644 docs/ux/mockups/rich__sk_arc__modify.svg create mode 100644 docs/ux/mockups/rich__sk_arc__reference.svg create mode 100644 docs/ux/mockups/rich__sk_line.svg create mode 100644 docs/ux/mockups/rich__sk_line__create.svg create mode 100644 docs/ux/mockups/rich__sk_line__dressup.svg create mode 100644 docs/ux/mockups/rich__sk_line__modify.svg create mode 100644 docs/ux/mockups/rich__sk_line__reference.svg create mode 100644 docs/ux/mockups/rich__sk_loop.svg create mode 100644 docs/ux/mockups/rich__sk_loop__add.svg create mode 100644 docs/ux/mockups/rich__sk_loop__modify.svg create mode 100644 docs/ux/mockups/rich__sk_none.svg create mode 100644 docs/ux/mockups/rich__sk_none__create.svg create mode 100644 docs/ux/mockups/rich__sk_none__reference.svg create mode 100644 docs/ux/mockups/rich__sk_point.svg create mode 100644 docs/ux/mockups/rich__sk_point__create.svg create mode 100644 docs/ux/mockups/rich__sk_point__reference.svg create mode 100644 docs/ux/mockups/rich__vertex.svg create mode 100644 docs/ux/mockups/rich__vertex__reference.svg create mode 100644 docs/ux/offer_atlas.html create mode 100644 docs/ux/offer_atlas_inline.html create mode 100644 docs/ux/tool_atlas.json diff --git a/docs/ux/mockups/cmp_12__edge_str.svg b/docs/ux/mockups/cmp_12__edge_str.svg new file mode 100644 index 0000000000..3e641e90ec --- /dev/null +++ b/docs/ux/mockups/cmp_12__edge_str.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Straight edge selected — pick what to do with itWorking document · 12 slotsDress-up2Pattern on CurveReference3Straight edge \ No newline at end of file diff --git a/docs/ux/mockups/cmp_12__face_planar.svg b/docs/ux/mockups/cmp_12__face_planar.svg new file mode 100644 index 0000000000..85809d5bf6 --- /dev/null +++ b/docs/ux/mockups/cmp_12__face_planar.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Planar face selected — pick what to do with itWorking document · 12 slotsSketchShift+SAdd material2Remove2Dress-up3PatternShift+NTransform2Reference5Modify2Planar face \ No newline at end of file diff --git a/docs/ux/mockups/cmp_12__sk_line.svg b/docs/ux/mockups/cmp_12__sk_line.svg new file mode 100644 index 0000000000..6535c9fe77 --- /dev/null +++ b/docs/ux/mockups/cmp_12__sk_line.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch line selected — pick what to do with itWorking document · 12 slotsCreate9OffsetOTrimTDress-up2MirrorMMoveReference3Modify2Sketch line \ No newline at end of file diff --git a/docs/ux/mockups/cmp_8__edge_str.svg b/docs/ux/mockups/cmp_8__edge_str.svg new file mode 100644 index 0000000000..2c41ce74fc --- /dev/null +++ b/docs/ux/mockups/cmp_8__edge_str.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Straight edge selected — pick what to do with itWorking document · 8 slotsDress-up2Pattern on CurveReference3Straight edge \ No newline at end of file diff --git a/docs/ux/mockups/cmp_8__face_planar.svg b/docs/ux/mockups/cmp_8__face_planar.svg new file mode 100644 index 0000000000..5a58e2fb72 --- /dev/null +++ b/docs/ux/mockups/cmp_8__face_planar.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Planar face selected — pick what to do with itWorking document · 8 slotsSketchShift+SAdd material2Remove2Dress-up3PatternShift+NTransform2Reference5Modify2Planar face \ No newline at end of file diff --git a/docs/ux/mockups/cmp_8__sk_line.svg b/docs/ux/mockups/cmp_8__sk_line.svg new file mode 100644 index 0000000000..4ca4000d59 --- /dev/null +++ b/docs/ux/mockups/cmp_8__sk_line.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch line selected — pick what to do with itWorking document · 8 slotsCreate9OffsetOTrimTDress-up2MirrorMMoveReference3Modify2Sketch line \ No newline at end of file diff --git a/docs/ux/mockups/fresh__art.svg b/docs/ux/mockups/fresh__art.svg new file mode 100644 index 0000000000..a54dd49b43 --- /dev/null +++ b/docs/ux/mockups/fresh__art.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetText / imported art selected — pick what to do with itFresh document · 8 slotsABCModify2Text / imported art \ No newline at end of file diff --git a/docs/ux/mockups/fresh__art__modify.svg b/docs/ux/mockups/fresh__art__modify.svg new file mode 100644 index 0000000000..184611c682 --- /dev/null +++ b/docs/ux/mockups/fresh__art__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetModify — pick oneFresh document · 8 slotsABCDeleteDelEditText / imported art · Modify \ No newline at end of file diff --git a/docs/ux/mockups/fresh__bodies_2.svg b/docs/ux/mockups/fresh__bodies_2.svg new file mode 100644 index 0000000000..f282bef03a --- /dev/null +++ b/docs/ux/mockups/fresh__bodies_2.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetTwo bodies selected — pick what to do with itFresh document · 8 slotsMeasureDeleteDelTwo bodies \ No newline at end of file diff --git a/docs/ux/mockups/fresh__body_sheet.svg b/docs/ux/mockups/fresh__body_sheet.svg new file mode 100644 index 0000000000..635b2f6aa6 --- /dev/null +++ b/docs/ux/mockups/fresh__body_sheet.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetSheet body selected — pick what to do with itFresh document · 8 slotsMeasureModify2Sheet body \ No newline at end of file diff --git a/docs/ux/mockups/fresh__body_sheet__modify.svg b/docs/ux/mockups/fresh__body_sheet__modify.svg new file mode 100644 index 0000000000..0cd330046d --- /dev/null +++ b/docs/ux/mockups/fresh__body_sheet__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetModify — pick oneFresh document · 8 slotsDeleteDelEditSheet body · Modify \ No newline at end of file diff --git a/docs/ux/mockups/fresh__body_solid.svg b/docs/ux/mockups/fresh__body_solid.svg new file mode 100644 index 0000000000..ef21e2b8e2 --- /dev/null +++ b/docs/ux/mockups/fresh__body_solid.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetSolid body selected — pick what to do with itFresh document · 8 slotsMeasureModify2Solid body \ No newline at end of file diff --git a/docs/ux/mockups/fresh__body_solid__modify.svg b/docs/ux/mockups/fresh__body_solid__modify.svg new file mode 100644 index 0000000000..8b5d1485a0 --- /dev/null +++ b/docs/ux/mockups/fresh__body_solid__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetModify — pick oneFresh document · 8 slotsDeleteDelEditSolid body · Modify \ No newline at end of file diff --git a/docs/ux/mockups/fresh__coordsys.svg b/docs/ux/mockups/fresh__coordsys.svg new file mode 100644 index 0000000000..e20d08d000 --- /dev/null +++ b/docs/ux/mockups/fresh__coordsys.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetCoordinate system selected — pick what to do with itFresh document · 8 slotsModify2Coordinate system \ No newline at end of file diff --git a/docs/ux/mockups/fresh__coordsys__modify.svg b/docs/ux/mockups/fresh__coordsys__modify.svg new file mode 100644 index 0000000000..b6b4871d16 --- /dev/null +++ b/docs/ux/mockups/fresh__coordsys__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetModify — pick oneFresh document · 8 slotsDeleteDelEditCoordinate system · Modify \ No newline at end of file diff --git a/docs/ux/mockups/fresh__datum_axis.svg b/docs/ux/mockups/fresh__datum_axis.svg new file mode 100644 index 0000000000..8174807ceb --- /dev/null +++ b/docs/ux/mockups/fresh__datum_axis.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetDatum axis selected — pick what to do with itFresh document · 8 slotsModify2Datum axis \ No newline at end of file diff --git a/docs/ux/mockups/fresh__datum_axis__modify.svg b/docs/ux/mockups/fresh__datum_axis__modify.svg new file mode 100644 index 0000000000..cba7005358 --- /dev/null +++ b/docs/ux/mockups/fresh__datum_axis__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetModify — pick oneFresh document · 8 slotsDeleteDelEditDatum axis · Modify \ No newline at end of file diff --git a/docs/ux/mockups/fresh__datum_plane.svg b/docs/ux/mockups/fresh__datum_plane.svg new file mode 100644 index 0000000000..ffabd59969 --- /dev/null +++ b/docs/ux/mockups/fresh__datum_plane.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetDatum plane selected — pick what to do with itFresh document · 8 slotsSketchShift+SReference2Modify2Datum plane \ No newline at end of file diff --git a/docs/ux/mockups/fresh__datum_plane__modify.svg b/docs/ux/mockups/fresh__datum_plane__modify.svg new file mode 100644 index 0000000000..9ac26e4ce1 --- /dev/null +++ b/docs/ux/mockups/fresh__datum_plane__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetModify — pick oneFresh document · 8 slotsDeleteDelEditDatum plane · Modify \ No newline at end of file diff --git a/docs/ux/mockups/fresh__datum_plane__reference.svg b/docs/ux/mockups/fresh__datum_plane__reference.svg new file mode 100644 index 0000000000..b42479441a --- /dev/null +++ b/docs/ux/mockups/fresh__datum_plane__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetReference — pick oneFresh document · 8 slotsPlaneShift+PHelixDatum plane · Reference \ No newline at end of file diff --git a/docs/ux/mockups/fresh__edge_circ.svg b/docs/ux/mockups/fresh__edge_circ.svg new file mode 100644 index 0000000000..3e72544c04 --- /dev/null +++ b/docs/ux/mockups/fresh__edge_circ.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetCircular edge selected — pick what to do with itFresh document · 8 slotsMeasureCircular edge \ No newline at end of file diff --git a/docs/ux/mockups/fresh__edge_str.svg b/docs/ux/mockups/fresh__edge_str.svg new file mode 100644 index 0000000000..c4e54d5335 --- /dev/null +++ b/docs/ux/mockups/fresh__edge_str.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetStraight edge selected — pick what to do with itFresh document · 8 slotsReference3Straight edge \ No newline at end of file diff --git a/docs/ux/mockups/fresh__edge_str__reference.svg b/docs/ux/mockups/fresh__edge_str__reference.svg new file mode 100644 index 0000000000..80dd7a877a --- /dev/null +++ b/docs/ux/mockups/fresh__edge_str__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetReference — pick oneFresh document · 8 slotsMeasurePlaneShift+PAxisShift+AStraight edge · Reference \ No newline at end of file diff --git a/docs/ux/mockups/fresh__face_cyl.svg b/docs/ux/mockups/fresh__face_cyl.svg new file mode 100644 index 0000000000..d2335e4177 --- /dev/null +++ b/docs/ux/mockups/fresh__face_cyl.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetCylindrical face selected — pick what to do with itFresh document · 8 slotsReference3EditCylindrical face \ No newline at end of file diff --git a/docs/ux/mockups/fresh__face_cyl__reference.svg b/docs/ux/mockups/fresh__face_cyl__reference.svg new file mode 100644 index 0000000000..7cb83afb56 --- /dev/null +++ b/docs/ux/mockups/fresh__face_cyl__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetReference — pick oneFresh document · 8 slotsMeasureAxisShift+AHelixCylindrical face · Reference \ No newline at end of file diff --git a/docs/ux/mockups/fresh__face_other.svg b/docs/ux/mockups/fresh__face_other.svg new file mode 100644 index 0000000000..d8dcfb96ab --- /dev/null +++ b/docs/ux/mockups/fresh__face_other.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetCurved face selected — pick what to do with itFresh document · 8 slotsMeasureEditCurved face \ No newline at end of file diff --git a/docs/ux/mockups/fresh__face_planar.svg b/docs/ux/mockups/fresh__face_planar.svg new file mode 100644 index 0000000000..a66268fc9a --- /dev/null +++ b/docs/ux/mockups/fresh__face_planar.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetPlanar face selected — pick what to do with itFresh document · 8 slotsSketchShift+SExtrudeShift+EReference4EditPlanar face \ No newline at end of file diff --git a/docs/ux/mockups/fresh__face_planar__reference.svg b/docs/ux/mockups/fresh__face_planar__reference.svg new file mode 100644 index 0000000000..9aa608a5e7 --- /dev/null +++ b/docs/ux/mockups/fresh__face_planar__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetReference — pick oneFresh document · 8 slotsCoord SysShift+CMeasurePlaneShift+PAxisShift+APlanar face · Reference \ No newline at end of file diff --git a/docs/ux/mockups/fresh__none.svg b/docs/ux/mockups/fresh__none.svg new file mode 100644 index 0000000000..56ac028b74 --- /dev/null +++ b/docs/ux/mockups/fresh__none.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetClick a face or a reference plane, then a toolFresh document · 8 slotsSketchShift+SReference4Nothing selected \ No newline at end of file diff --git a/docs/ux/mockups/fresh__none__reference.svg b/docs/ux/mockups/fresh__none__reference.svg new file mode 100644 index 0000000000..0492aa6de0 --- /dev/null +++ b/docs/ux/mockups/fresh__none__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetReference — pick oneFresh document · 8 slotsCoord SysShift+CHelixPlaneShift+PAxisShift+ANothing selected · Reference \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_2ent.svg b/docs/ux/mockups/fresh__sk_2ent.svg new file mode 100644 index 0000000000..dd02122149 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_2ent.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetTwo sketch entities selected — pick what to do with itFresh document · 8 slotsCreate9OffsetOTrimTDress-up2MirrorMMoveReference3Modify2Two sketch entities \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_2ent__create.svg b/docs/ux/mockups/fresh__sk_2ent__create.svg new file mode 100644 index 0000000000..98e984bff2 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_2ent__create.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetCreate — pick oneFresh document · 8 slotsLineLRectangleRCircleCArcASlotSEllipseESplineBMore2Two sketch entities · Create \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_2ent__dressup.svg b/docs/ux/mockups/fresh__sk_2ent__dressup.svg new file mode 100644 index 0000000000..926594bb86 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_2ent__dressup.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetDress-up — pick oneFresh document · 8 slotsFilletFChamferHTwo sketch entities · Dress-up \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_2ent__modify.svg b/docs/ux/mockups/fresh__sk_2ent__modify.svg new file mode 100644 index 0000000000..242332967e --- /dev/null +++ b/docs/ux/mockups/fresh__sk_2ent__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetModify — pick oneFresh document · 8 slotsDeleteDelExtendXTwo sketch entities · Modify \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_2ent__reference.svg b/docs/ux/mockups/fresh__sk_2ent__reference.svg new file mode 100644 index 0000000000..aa105c3a9e --- /dev/null +++ b/docs/ux/mockups/fresh__sk_2ent__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetReference — pick oneFresh document · 8 slotsConstructionQDimensionDConstrainKTwo sketch entities · Reference \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_arc.svg b/docs/ux/mockups/fresh__sk_arc.svg new file mode 100644 index 0000000000..0712508411 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_arc.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetSketch arc or circle selected — pick what to do with itFresh document · 8 slotsCreate9OffsetOTrimTMirrorMMoveReference3Modify2Sketch arc or circle \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_arc__create.svg b/docs/ux/mockups/fresh__sk_arc__create.svg new file mode 100644 index 0000000000..d22d916e60 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_arc__create.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetCreate — pick oneFresh document · 8 slotsLineLRectangleRCircleCArcASlotSEllipseESplineBMore2Sketch arc or circle · Create \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_arc__modify.svg b/docs/ux/mockups/fresh__sk_arc__modify.svg new file mode 100644 index 0000000000..cf3fc2450f --- /dev/null +++ b/docs/ux/mockups/fresh__sk_arc__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetModify — pick oneFresh document · 8 slotsDeleteDelExtendXSketch arc or circle · Modify \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_arc__reference.svg b/docs/ux/mockups/fresh__sk_arc__reference.svg new file mode 100644 index 0000000000..cfbe0a1042 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_arc__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetReference — pick oneFresh document · 8 slotsConstructionQDimensionDConstrainKSketch arc or circle · Reference \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_line.svg b/docs/ux/mockups/fresh__sk_line.svg new file mode 100644 index 0000000000..e40d823e13 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_line.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetSketch line selected — pick what to do with itFresh document · 8 slotsCreate9OffsetOTrimTDress-up2MirrorMMoveReference3Modify2Sketch line \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_line__create.svg b/docs/ux/mockups/fresh__sk_line__create.svg new file mode 100644 index 0000000000..1a6f7b561c --- /dev/null +++ b/docs/ux/mockups/fresh__sk_line__create.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetCreate — pick oneFresh document · 8 slotsLineLRectangleRCircleCArcASlotSEllipseESplineBMore2Sketch line · Create \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_line__dressup.svg b/docs/ux/mockups/fresh__sk_line__dressup.svg new file mode 100644 index 0000000000..3fce662ba1 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_line__dressup.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetDress-up — pick oneFresh document · 8 slotsFilletFChamferHSketch line · Dress-up \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_line__modify.svg b/docs/ux/mockups/fresh__sk_line__modify.svg new file mode 100644 index 0000000000..26318535ef --- /dev/null +++ b/docs/ux/mockups/fresh__sk_line__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetModify — pick oneFresh document · 8 slotsDeleteDelExtendXSketch line · Modify \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_line__reference.svg b/docs/ux/mockups/fresh__sk_line__reference.svg new file mode 100644 index 0000000000..2abc91fc99 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_line__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetReference — pick oneFresh document · 8 slotsConstructionQDimensionDConstrainKSketch line · Reference \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_loop.svg b/docs/ux/mockups/fresh__sk_loop.svg new file mode 100644 index 0000000000..58eaa9e4fb --- /dev/null +++ b/docs/ux/mockups/fresh__sk_loop.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetClosed sketch loop selected — pick what to do with itFresh document · 8 slotsAdd material5Modify2Closed sketch loop \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_loop__add.svg b/docs/ux/mockups/fresh__sk_loop__add.svg new file mode 100644 index 0000000000..c6e6c90701 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_loop__add.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetAdd material — pick oneFresh document · 8 slotsExtrudeShift+ERevolveShift+RSurface ExtrudeShift+GSurface RevolveSurface FillClosed sketch loop · Add material \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_loop__modify.svg b/docs/ux/mockups/fresh__sk_loop__modify.svg new file mode 100644 index 0000000000..416e62d7cd --- /dev/null +++ b/docs/ux/mockups/fresh__sk_loop__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetModify — pick oneFresh document · 8 slotsDeleteDelEditClosed sketch loop · Modify \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_none.svg b/docs/ux/mockups/fresh__sk_none.svg new file mode 100644 index 0000000000..ce7604c47d --- /dev/null +++ b/docs/ux/mockups/fresh__sk_none.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetSketch, nothing picked selected — pick what to do with itFresh document · 8 slotsCreate9Reference2Sketch, nothing picked \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_none__create.svg b/docs/ux/mockups/fresh__sk_none__create.svg new file mode 100644 index 0000000000..06994f9517 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_none__create.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetCreate — pick oneFresh document · 8 slotsLineLRectangleRCircleCArcASlotSEllipseESplineBMore2Sketch, nothing picked · Create \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_none__reference.svg b/docs/ux/mockups/fresh__sk_none__reference.svg new file mode 100644 index 0000000000..e4e558bbd9 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_none__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetReference — pick oneFresh document · 8 slotsDimensionDConstructionQSketch, nothing picked · Reference \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_point.svg b/docs/ux/mockups/fresh__sk_point.svg new file mode 100644 index 0000000000..65acf94ac7 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_point.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetSketch point selected — pick what to do with itFresh document · 8 slotsCreate9MoveReference2DeleteDelSketch point \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_point__create.svg b/docs/ux/mockups/fresh__sk_point__create.svg new file mode 100644 index 0000000000..fbe094d147 --- /dev/null +++ b/docs/ux/mockups/fresh__sk_point__create.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetCreate — pick oneFresh document · 8 slotsLineLRectangleRCircleCArcASlotSEllipseESplineBMore2Sketch point · Create \ No newline at end of file diff --git a/docs/ux/mockups/fresh__sk_point__reference.svg b/docs/ux/mockups/fresh__sk_point__reference.svg new file mode 100644 index 0000000000..8b02eba29f --- /dev/null +++ b/docs/ux/mockups/fresh__sk_point__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetReference — pick oneFresh document · 8 slotsDimensionDConstrainKSketch point · Reference \ No newline at end of file diff --git a/docs/ux/mockups/fresh__vertex.svg b/docs/ux/mockups/fresh__vertex.svg new file mode 100644 index 0000000000..1e1661d6aa --- /dev/null +++ b/docs/ux/mockups/fresh__vertex.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetVertex selected — pick what to do with itFresh document · 8 slotsReference4Vertex \ No newline at end of file diff --git a/docs/ux/mockups/fresh__vertex__reference.svg b/docs/ux/mockups/fresh__vertex__reference.svg new file mode 100644 index 0000000000..aad3d46b6e --- /dev/null +++ b/docs/ux/mockups/fresh__vertex__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESnothing yetReference — pick oneFresh document · 8 slotsCoord SysShift+CMeasurePlaneShift+PAxisShift+AVertex · Reference \ No newline at end of file diff --git a/docs/ux/mockups/gen_offer_mockups.py b/docs/ux/mockups/gen_offer_mockups.py new file mode 100644 index 0000000000..b2379df846 --- /dev/null +++ b/docs/ux/mockups/gen_offer_mockups.py @@ -0,0 +1,736 @@ +#!/usr/bin/env python3 +"""Render the object-driven tool offer from docs/ux/tool_atlas.json. + +Fork-neutral on purpose: this file and everything it emits name no product, so the +two forks carry byte-identical copies (the charter itself is the only doc that +substitutes the product name). + +Every mockup in docs/ux/mockups/ and the review page docs/ux/offer_atlas.html are +generated by this script. Nothing is hand-drawn: the point of the offer is that a +tool's address never changes, and a human drawing 40-odd states by hand is exactly +how an address quietly changes. + + python3 docs/ux/mockups/gen_offer_mockups.py + +It fails loudly rather than rendering a broken map: an unknown slot, an unknown +selection id in `accepts`, or one address holding two different verbs for the same +selection is an error, not a warning. + +SVG on purpose. There is no rsvg/inkscape/cairosvg on the build box and +ImageMagick would rasterise through its own weak internal renderer; SVG renders +exactly in a browser at any zoom and stays diffable in git. Rasterise later if +slides need it. +""" + +import json +import re +import math +import os +import sys +from collections import defaultdict + +HERE = os.path.dirname(os.path.abspath(__file__)) +UX = os.path.dirname(HERE) +ATLAS = os.path.join(UX, "tool_atlas.json") + +# The reach target from the charter (L11 / 6.1): if the ring plus a real part do not +# fit here, the design has failed before it is built. +W, H = 1366, 768 + +C = { + "app": "#1a1d21", "chrome": "#23272d", "panel": "#20242a", "line": "#31363d", + "vp0": "#2f353d", "vp1": "#242930", "grid": "#333a43", + "text": "#e7ecf1", "muted": "#8e9aa7", "dim": "#5f6a76", + "top": "#93a1b1", "left": "#6f7b89", "right": "#5a6472", "edge": "#39414b", + "hi": "#f5a623", "hi_soft": "#f5a62333", "sheet": "#7fa8c9", + "ring": "#171a1e", "chip": "#2e343c", "chip_line": "#3c444e", + "key": "#454f5b", "accent": "#4f9bd9", "empty": "#2a2f36", +} + + +# ---------------------------------------------------------------- glyphs +# Each glyph draws inside a 24x24 box centred on (0,0) — i.e. -12..12. +def _g(body): + return body + + +GLYPHS = { + # model + "sketch": '', + "extrude": '', + "revolve": '', + "sweep": '', + "loft": '', + "thicken": '', + "rib": '', + "boolean": '', + "hole": '', + "thread": '', + "shell": '', + "cut": '', + "split": '', + "fillet": '', + "chamfer": '', + "draft": '', + "surf_off": '', + "pattern": '', + "mirror": '', + "pat_curve": '', + "move": '', + "mate": '', + "align": '', + "plane": '', + "axis": '', + "csys": '', + "helix": '', + "project": '', + "measure": '', + "mass": '', + "interfere": '', + "edit": '', + "del_face": '', + "colour": '', + "delete": '', + # sketch primitives + "sk_line": '', + "sk_rect": '', + "sk_circle": '', + "sk_arc": '', + "sk_slot": '', + "sk_ell": '', + "sk_spline": '', + "sk_poly": '', + "sk_point": '', + "sk_offset": '', + "sk_trim": '', + "sk_ext": '', + "sk_mir": '', + "sk_move": '', + "sk_dim": '', + "sk_lock": '', + "sk_constr": '', + # families (used when a slot holds more than one verb) + "fam_create": '', + "fam_add": '', + "fam_remove": '', + "fam_dressup": '', + "fam_repeat": '', + "fam_transform": '', + "fam_reference": '', + # Deliberately NOT the bare pencil: create/sketch already owns that shape and the two slots + # are adjacent (N and NW). A pencil over a solid reads as "change the thing that exists". + "fam_modify": '' + '', +} + +VERB_GLYPH = { + "sketch": "sketch", "extrude": "extrude", "revolve": "revolve", "sweep": "sweep", + "loft": "loft", "thicken": "thicken", "rib": "rib", "boolean": "boolean", + "surf_extrude": "extrude", "surf_revolve": "revolve", "surf_loft": "loft", + "surf_fill": "surf_off", "thicken_surf": "thicken", "hole": "hole", "thread": "thread", + "shell": "shell", "cut": "cut", "split": "split", "fillet": "fillet", + "chamfer": "chamfer", "draft": "draft", "surf_offset": "surf_off", + "pattern": "pattern", "mirror": "mirror", "pat_curve": "pat_curve", + "transform": "move", "mate": "mate", "align": "align", "plane": "plane", + "axis": "axis", "coordsys_v": "csys", "helix": "helix", "project": "project", + "measure": "measure", "mass_props": "mass", "interference": "interfere", + "edit_feature": "edit", "delete_face": "del_face", "colour": "colour", "delete": "delete", + "sk_line_t": "sk_line", "sk_rect": "sk_rect", "sk_circle": "sk_circle", + "sk_arc_t": "sk_arc", "sk_slot": "sk_slot", "sk_ellipse": "sk_ell", + "sk_spline": "sk_spline", "sk_polygon": "sk_poly", "sk_point_t": "sk_point", + "sk_offset": "sk_offset", "sk_trim": "sk_trim", "sk_fillet": "fillet", + "sk_chamfer": "chamfer", "sk_mirror": "sk_mir", "sk_move": "sk_move", + "sk_dimension": "sk_dim", "sk_constrain": "sk_lock", "sk_construct": "sk_constr", + "sk_extend": "sk_ext", "sk_delete": "delete", +} + + +def glyph(name, cx, cy, colour, scale=1.0, sw=1.6): + body = GLYPHS.get(name, '') + return (f'{body}') + + +# ---------------------------------------------------------------- iso scene +COS30, SIN30 = math.cos(math.radians(30)), math.sin(math.radians(30)) + + +def iso(x, y, z, ox, oy, s=1.0): + return (ox + (x - y) * COS30 * s, oy + (x + y) * SIN30 * s - z * s) + + +def poly(pts, fill, stroke=None, extra=""): + d = " ".join(f"{x:.1f},{y:.1f}" for x, y in pts) + # Only emit our own stroke-width when the caller has not supplied one: a duplicate + # attribute is last-one-wins in a browser but invalid markup, and it is exactly the + # kind of thing a stricter renderer refuses outright. + if stroke: + st = f' stroke="{stroke}"' + ("" if "stroke-width" in extra else ' stroke-width="1"') + else: + st = ' stroke="none"' + return f'' + + +def box(ox, oy, w=150, d=105, h=52, s=1.0, hi=None): + """Three visible faces of a box. `hi` names the face/edge to highlight.""" + P = lambda x, y, z: iso(x, y, z, ox, oy, s) + top = [P(0, 0, h), P(w, 0, h), P(w, d, h), P(0, d, h)] + left = [P(0, d, h), P(w, d, h), P(w, d, 0), P(0, d, 0)] + right = [P(w, 0, h), P(w, d, h), P(w, d, 0), P(w, 0, 0)] + out = [ + poly(left, C["left"], C["edge"]), + poly(right, C["right"], C["edge"]), + poly(top, C["hi"] if hi == "top" else C["top"], C["edge"]), + ] + if hi == "top": + out.append(poly(top, "none", "#ffd07a", ' stroke-width="2.5"')) + if hi == "front_edge": + a, b = P(0, d, h), P(w, d, h) + out.append(f'') + if hi == "vertex": + v = P(w, d, h) + out.append(f'') + if hi == "whole": + out.append(poly(top, "none", "#ffd07a", ' stroke-width="2.5"')) + out.append(poly(left, "none", "#ffd07a", ' stroke-width="2.5"')) + out.append(poly(right, "none", "#ffd07a", ' stroke-width="2.5"')) + return "".join(out), P + + +def bore(P, cx, cy, h, r=22, s=1.0, hi=False): + """A cylindrical bore through the top face, drawn as ellipse + wall.""" + c = P(cx, cy, h) + rx, ry = r * COS30 * 2 * s, r * SIN30 * 2 * s + col = C["hi"] if hi else "#20252b" + wall = C["hi"] if hi == "wall" else "#3b434d" + return (f'' + f'' + + (f'' if hi else "")), c + + +def scene(kind, ox, oy): + """Return (svg, anchor) for a selection kind. Anchor = where the ring centres.""" + s = 1.0 + if kind == "origin": + # A document with nothing in it: the three origin planes are all there is to click. + P = lambda x, y, z: iso(x, y, z, ox, oy, s) + g = poly([P(-70, -70, 0), P(70, -70, 0), P(70, 70, 0), P(-70, 70, 0)], + "#4f9bd91f", "#4f9bd977", ' stroke-width="1.5" stroke-dasharray="6 4"') + g += poly([P(-70, 0, -70), P(70, 0, -70), P(70, 0, 70), P(-70, 0, 70)], + "#e05c5c14", "#e05c5c66", ' stroke-width="1.5" stroke-dasharray="6 4"') + g += poly([P(0, -70, -70), P(0, 70, -70), P(0, 70, 70), P(0, -70, 70)], + "#5ce07a14", "#5ce07a66", ' stroke-width="1.5" stroke-dasharray="6 4"') + return g, P(0, 0, 0) + if kind == "empty": + g, P = box(ox, oy, s=s) + return g, P(75, 52, 26) + if kind == "box_top": + g, P = box(ox, oy, s=s, hi="top") + return g, P(75, 52, 52) + if kind == "box_whole": + g, P = box(ox, oy, s=s, hi="whole") + return g, P(75, 52, 26) + if kind == "box_edge": + g, P = box(ox, oy, s=s, hi="front_edge") + return g, P(75, 105, 52) + if kind == "box_vertex": + g, P = box(ox, oy, s=s, hi="vertex") + return g, P(150, 105, 52) + if kind in ("box_bore", "box_bore_rim"): + g, P = box(ox, oy, s=s) + b, c = bore(P, 75, 52, 52, hi=("wall" if kind == "box_bore" else True)) + return g + b, c + if kind == "box_fillet_face": + g, P = box(ox, oy, s=s) + a, b = P(0, 0, 52), P(0, 105, 52) + g += (f'') + return g, P(0, 52, 52) + if kind == "sheet": + P = lambda x, y, z: iso(x, y, z, ox, oy, s) + pts = [P(0, 0, 40), P(150, 0, 55), P(150, 105, 30), P(0, 105, 18)] + return (poly(pts, C["sheet"], "#ffd07a", ' stroke-width="2.5" opacity="0.85"'), + P(75, 52, 36)) + if kind == "two_boxes": + g1, P1 = box(ox - 60, oy - 10, w=110, d=80, h=44, hi="whole") + g2, P2 = box(ox + 70, oy + 26, w=95, d=70, h=60, hi="whole") + return g1 + g2, (ox + 42, oy + 6) + if kind == "datum": + P = lambda x, y, z: iso(x, y, z, ox, oy, s) + g, _ = box(ox, oy, s=s) + pts = [P(-25, -25, 70), P(175, -25, 70), P(175, 130, 70), P(-25, 130, 70)] + g += poly(pts, "#4f9bd933", C["hi"], ' stroke-width="2.5" stroke-dasharray="6 4"') + return g, P(75, 52, 70) + if kind == "axis": + g, P = box(ox, oy, s=s) + a, b = P(-30, 52, 52), P(180, 52, 52) + g += (f'') + return g, P(75, 52, 52) + if kind == "csys": + P = lambda x, y, z: iso(x, y, z, ox, oy, s) + g, _ = box(ox, oy, s=s) + o = P(0, 0, 52) + for tgt, col in ((P(60, 0, 52), "#e05c5c"), (P(0, 60, 52), "#5ce07a"), (P(0, 0, 112), "#5c9ce0")): + g += (f'') + g += f'' + return g, o + if kind == "art": + P = lambda x, y, z: iso(x, y, z, ox, oy, s) + g, _ = box(ox, oy, s=s) + c = P(75, 52, 52) + g += (f'' + f'ABC') + return g, c + if kind == "loop": + P = lambda x, y, z: iso(x, y, z, ox, oy, s) + g, _ = box(ox, oy, s=s) + pts = [P(28, 22, 52), P(122, 22, 52), P(122, 83, 52), P(28, 83, 52)] + g += poly(pts, C["hi_soft"], C["hi"], ' stroke-width="3"') + return g, P(75, 52, 52) + # --- sketch mode: flat, camera normal to the plane + gx, gy = ox - 30, oy - 10 + grid = "".join( + f'' + for i in range(11)) + "".join( + f'' + for i in range(16)) + if kind == "sk_empty": + return grid, (gx, gy) + if kind == "sk_line": + return (grid + f'' + f'' + f'', (gx, gy + 10)) + if kind == "sk_arc": + return (grid + f'', (gx, gy)) + if kind == "sk_point": + return (grid + f'', (gx, gy)) + if kind == "sk_two": + return (grid + f'' + f'', (gx, gy + 5)) + return grid, (gx, gy) + + +# ---------------------------------------------------------------- app chrome +def chrome(title, status, mode="model", empty_doc=False): + tabs = ["Prepare", "Preview", "Design"] + g = [f'', + f'' + f'' + f'', + f'', + f''] + x = 24 + for t in tabs: + on = (t == "Design") + g.append(f'{t}') + if on: + g.append(f'') + x += len(t) * 9 + 34 + # toolbar + g.append(f'' + f'') + fams = (["sketch", "extrude", "hole", "fillet", "pattern", "boolean", "plane", "move", "measure"] + if mode == "model" else + ["sk_line", "sk_rect", "sk_circle", "sk_arc", "sk_slot", "sk_spline", "sk_dim", "sk_trim", "sk_lock"]) + for i, gl in enumerate(fams): + cx = 40 + i * 46 + g.append(f'') + g.append(glyph(gl, cx, 68, C["muted"], 0.62, 1.7)) + # left rail + g.append(f'' + f'') + g.append(f'FEATURES') + # A "fresh document" mockup that shows six existing features is a lie, and it is the one + # state the group will look at hardest — it is the first-run picture (B5). + tree = ([] if empty_doc else + [("Sketch1", 0), ("Extrude1", 0), ("Hole1", 1), ("Fillet1", 1), ("Sketch2", 0), ("Extrude2", 0)]) + if empty_doc: + g.append(f'nothing yet') + for i, (n, ind) in enumerate(tree): + yy = 150 + i * 26 + g.append(glyph("sketch" if n.startswith("Sketch") else "extrude", 30 + ind * 14, yy - 4, C["dim"], 0.42, 1.8)) + g.append(f'{n}') + # status bar + g.append(f'' + f'{status}') + g.append(f'{title}') + return "".join(g) + + +# ---------------------------------------------------------------- the ring +def ring(cx, cy, items, capacity, sel_name, radius=134): + """items: dict angle_index -> (glyph, label, key, count) or None for an empty slot.""" + # The scrim is deliberately faint. §4.1: the offer "never blocks the view of what it acts + # on" — at 0.55 the disc swallowed the very face the ring was opened on, which is the rule + # failing in its own mockup. + g = [f'', + f'', + f''] + step = 360.0 / capacity + for i in range(capacity): + ang = math.radians(-90 + i * step) + px, py = cx + radius * math.cos(ang), cy + radius * math.sin(ang) + it = items.get(i) + if not it: + g.append(f'') + continue + gl, label, key, count = it + g.append(f'') + g.append(glyph(gl, px, py - 2, C["text"], 0.92, 1.7)) + g.append(f'{label}') + if key: + kw = 13 + len(key) * 6.6 + g.append(f'' + f'{key}') + if count and count > 1: + g.append(f'' + f'{count}') + # The selection name sits on the LOWER rim of the centre hole, not above it: above, it + # landed on top of the north slot's shortcut chip and hid it. Below, the pick stays + # visible through the hole and the pill is clear of the south chip at cy+104. + w = 13 + len(sel_name) * 6.9 + g.append(f'' + f'{sel_name}') + return "".join(g) + + +# ---------------------------------------------------------------- enumeration +def load(): + with open(ATLAS, encoding="utf-8") as f: + return json.load(f) + + +def validate(A): + slot_ids = {s["id"] for s in A["slots"]} + sel_ids = {s["id"] for s in A["selections"]} + errs = [] + seen = {} + for v in A["verbs"]: + if v["slot"] not in slot_ids: + errs.append(f'{v["id"]}: unknown slot {v["slot"]!r}') + for a in v["accepts"]: + if a not in sel_ids: + errs.append(f'{v["id"]}: accepts unknown selection {a!r}') + if v["id"] in seen: + errs.append(f'{v["id"]}: duplicate verb id') + seen[v["id"]] = v["slot"] + if errs: + sys.exit("tool_atlas.json is inconsistent:\n " + "\n ".join(errs)) + return slot_ids, sel_ids + + +def eligible(A, sel_id, doc): + sel = next(s for s in A["selections"] if s["id"] == sel_id) + out = [] + for v in A["verbs"]: + if v.get("mode", "model") != sel["mode"]: + continue + if sel_id not in v["accepts"]: + continue + n = v.get("needs") or {} + if n.get("bodies", 0) > doc["bodies"]: + continue + if n.get("sketches", 0) > doc["sketches"]: + continue + if n.get("sheet") and not doc["sheet"]: + continue + out.append(v) + return out + + +def by_slot(A, verbs): + order = [s["id"] for s in A["slots"]] + d = defaultdict(list) + for v in verbs: + d[v["slot"]].append(v) + return {k: d[k] for k in order if d[k]} + + +def ring_items(A, grouped): + order = [s["id"] for s in A["slots"]] + slot_label = {s["id"]: s["label"] for s in A["slots"]} + items = {} + for i, sid in enumerate(order): + vs = grouped.get(sid) + if not vs: + continue + if len(vs) == 1: + v = vs[0] + items[i] = (VERB_GLYPH.get(v["id"], "fam_" + sid), v["name"], v.get("key"), 1) + else: + items[i] = ("fam_" + sid, slot_label[sid], None, len(vs)) + return items + + +# ---------------------------------------------------------------- rendering +OVERFLOWS = [] # (selection, doc state, family, verbs that did not fit the sub-ring) + + +def svg_doc(inner): + return (f'{inner}') + + +def render_state(A, sel, doc, capacity=8, secondary=None): + verbs = eligible(A, sel["id"], doc) + grouped = by_slot(A, verbs) + anchor_x, anchor_y = 810, 400 + fresh = doc["bodies"] == 0 and doc["sketches"] == 0 + shape = "origin" if (fresh and sel["shape"] == "empty") else sel["shape"] + art, (ax, ay) = scene(shape, anchor_x - 90, anchor_y - 40) + if secondary: + vs = grouped[secondary] + # A sub-ring ANCHORS ON ITS PARENT'S DIRECTION. Fanning from north instead put Extrude + # at N — Create's address in the primary map — so the second level contradicted the + # first. Anchored, an address is two consistent strokes: Add material is NE, and the + # first verb of Add material is NE again. + base = [s["id"] for s in A["slots"]].index(secondary) + overflow = [] + if len(vs) > capacity: + # Do NOT wrap: (base+i) % capacity would quietly put verb 9 on top of verb 1, which + # is the invariant failing silently — the one outcome worse than an ugly ring. Show + # what fits, mark the rest, and report it. + overflow = vs[capacity - 1:] + vs = vs[:capacity - 1] + items = {(base + i) % capacity: + (VERB_GLYPH.get(v["id"], "fam_" + secondary), v["name"], v.get("key"), 1) + for i, v in enumerate(vs)} + if overflow: + items[(base + capacity - 1) % capacity] = ("fam_" + secondary, "More", None, len(overflow)) + OVERFLOWS.append((sel["name"], doc["id"], secondary, [v["name"] for v in overflow])) + label = next(s["label"] for s in A["slots"] if s["id"] == secondary) + sel_name = f'{sel["name"]} · {label}' + status = f'{label} — pick one' + else: + items = ring_items(A, grouped) + sel_name = sel["name"] + status = ("Click a face or a reference plane, then a tool" + if sel["id"] == "none" else f'{sel["name"]} selected — pick what to do with it') + inner = chrome(f'{doc["name"]} · {capacity} slots', status, sel["mode"], empty_doc=fresh) + inner += art + inner += ring(ax, ay, items, capacity, sel_name) + return svg_doc(inner), verbs, grouped + + +def main(): + A = load() + validate(A) + docs = {d["id"]: d for d in A["doc_states"]} + outdir = HERE + rows, files = [], [] + total_primary = total_secondary = 0 + fill_sum = fill_n = 0 + + for d in A["doc_states"]: + for sel in A["selections"]: + svg, verbs, grouped = render_state(A, sel, d) + name = f'{d["id"]}__{sel["id"]}.svg' + with open(os.path.join(outdir, name), "w", encoding="utf-8") as f: + f.write(svg) + files.append((name, f'{sel["name"]} — {d["name"]}')) + total_primary += 1 + fill_sum += len(grouped) + fill_n += 1 + secondaries = [] + for sid, vs in grouped.items(): + if len(vs) > 1: + s2, _, _ = render_state(A, sel, d, secondary=sid) + n2 = f'{d["id"]}__{sel["id"]}__{sid}.svg' + with open(os.path.join(outdir, n2), "w", encoding="utf-8") as f: + f.write(s2) + label = next(s["label"] for s in A["slots"] if s["id"] == sid) + files.append((n2, f'{sel["name"]} — {label} ring')) + secondaries.append(sid) + total_secondary += 1 + rows.append({ + "doc": d["name"], "sel": sel["name"], "mode": sel["mode"], + "verbs": len(verbs), "slots": len(grouped), + "second": len(secondaries), + "detail": {sid: [v["name"] for v in vs] for sid, vs in grouped.items()}, + }) + + # comparison sheet: 8 vs 12 slots on the same three selections + for cap in (8, 12): + for sid in ("face_planar", "edge_str", "sk_line"): + sel = next(s for s in A["selections"] if s["id"] == sid) + svg, _, _ = render_state(A, sel, docs["rich"], capacity=cap) + n = f'cmp_{cap}__{sid}.svg' + with open(os.path.join(outdir, n), "w", encoding="utf-8") as f: + f.write(svg) + + write_atlas(A, rows, files, total_primary, total_secondary, + fill_sum / max(1, fill_n)) + print(f"{total_primary} primary + {total_secondary} secondary = " + f"{total_primary+total_secondary} offer states rendered") + print(f"mean populated slots per primary ring: {fill_sum/max(1,fill_n):.2f} of 8") + if OVERFLOWS: + seen = {(f, tuple(v)) for _, _, f, v in OVERFLOWS} + print(f"OVERFLOW: {len(OVERFLOWS)} sub-rings did not fit 8 slots — " + f"{len(seen)} distinct case(s):") + for f, v in sorted(seen): + print(f" {f}: {', '.join(v)} pushed behind 'More'") + + +def write_atlas(A, rows, files, n_prim, n_sec, mean_fill): + gui_missing = [v["name"] for v in A["verbs"] if not v.get("gui", True)] + esc = lambda s: (s.replace("&", "&").replace("<", "<").replace(">", ">")) + cards = "".join( + f'
{esc(t)}
{esc(t)}
' + for n, t in files) + cmp8 = "".join(f'
' + f'
8 slots — {s}
' + for s in ("face_planar", "edge_str", "sk_line")) + cmp12 = "".join(f'
' + f'
12 slots — {s}
' + for s in ("face_planar", "edge_str", "sk_line")) + if OVERFLOWS: + cases = sorted({(f, tuple(v)) for _, _, f, v in OVERFLOWS}) + over_html = ("Measured, not predicted: " + "; ".join( + f'the {esc(f)} sub-ring needs {8 + len(v)} addresses, so ' + f'{esc(", ".join(v))} {"is" if len(v) == 1 else "are"} pushed behind a “More” slot' + for f, v in cases) + + ". This is the decision the ring size actually turns on — either a verb moves to " + "another family, or the tail goes to a third level, or the ring is not eight. " + "It affects sketch mode only; every model-mode family fits.") + else: + over_html = "No sub-ring exceeds the ring capacity. Eight slots is sufficient everywhere." + trs = "".join( + f'{esc(r["sel"])}{esc(r["doc"])}{r["verbs"]}' + f'{r["slots"]}/8{r["second"]}' + f'{esc(" · ".join(k + ": " + ", ".join(v) for k, v in r["detail"].items()))}' + for r in rows) + html = f"""Design tab — offer atlas + +
+

The offer — atlas of every state

+

Every state of the object-driven tool offer, generated from + docs/ux/tool_atlas.json. The invariant under test: a verb has one address, that + address is the same in every selection where it appears, and slots that do not apply are drawn + empty rather than compacted.

+
+
{len(A["verbs"])}verbs mapped
+
{len(A["selections"])}selection kinds
+
{n_prim}primary rings
+
{n_sec}secondary rings
+
{n_prim+n_sec}states total
+
{mean_fill:.1f}/8mean slots filled
+
{len(gui_missing)}verbs with no GUI yet
+
+
+
+

Decision 1 — ring capacity

+

The same three selections at eight and at twelve. Eight keeps 45° between neighbours, which is + the reliable eyes-free pointing threshold and maps 1:1 to the numpad; twelve buys direct addresses + for more verbs at 30° spacing and positions that stop being nameable.

+
{cmp8}
+
{cmp12}
+ +

Decision 2 — one map or one per mode

+

These renders use ONE shared map: sketch verbs occupy the same eight families as model verbs, + so dress-up is south-east whether you picked a solid edge or a sketch line. Compare the sketch-mode + states below against the model-mode ones — if a verb that exists in both modes ever appears at two + addresses, the shared map has failed and the split map is the answer.

+ +

The matrix — every selection, every document state

+
+ + {trs} +
SelectionDocumentVerbsSlots2nd ringsWhat lands where
+ +

Overflow — the one place eight slots is not enough

+

{over_html}

+ +

Not in the offer

+

{esc(", ".join(A["chrome_only"]["items"]))} — these act on the document, not on a selection, + so they stay in chrome. Verbs with kernel support but no GUI today, which still hold an address: + {esc(", ".join(gui_missing))}.

+ +

All states

+
{cards}
+
+""" + with open(os.path.join(UX, "offer_atlas.html"), "w", encoding="utf-8") as f: + f.write(html) + + # A second, SELF-CONTAINED copy for review outside the repo: the artifact host blocks + # every external request, so relative would silently show nothing. Curated + # rather than all 113 states — the whole set inlined is 1.5 MB, which is a poor thing to + # send to the low-end machine this design is meant to serve (6.1). + def inline(name): + p = os.path.join(HERE, name) + if not os.path.exists(p): + return "" + s = open(p, encoding="utf-8").read() + return s.replace("{inline(n)}
{esc(t)}
' + for n, t in picks if inline(n)) + head, _, tail = html.partition('

All states

') + # The comparison grids in the head use , which resolves to nothing + # once the page is served on its own. Inline those too rather than shipping empty frames. + head = re.sub(r']*>', + lambda m: inline(m.group(1)), head) + inline_html = head + '

The states

\n
' + figs + '
\n' + with open(os.path.join(UX, "offer_atlas_inline.html"), "w", encoding="utf-8") as f: + f.write(inline_html) + + +if __name__ == "__main__": + main() diff --git a/docs/ux/mockups/rich__art.svg b/docs/ux/mockups/rich__art.svg new file mode 100644 index 0000000000..e835ed1ce0 --- /dev/null +++ b/docs/ux/mockups/rich__art.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Text / imported art selected — pick what to do with itWorking document · 8 slotsABCPatternShift+NMoveShift+YModify2Text / imported art \ No newline at end of file diff --git a/docs/ux/mockups/rich__art__modify.svg b/docs/ux/mockups/rich__art__modify.svg new file mode 100644 index 0000000000..4c8cdef2b5 --- /dev/null +++ b/docs/ux/mockups/rich__art__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsABCDeleteDelEditText / imported art · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__bodies_2.svg b/docs/ux/mockups/rich__bodies_2.svg new file mode 100644 index 0000000000..a977b7f1de --- /dev/null +++ b/docs/ux/mockups/rich__bodies_2.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Two bodies selected — pick what to do with itWorking document · 8 slotsCombineShift+BMateReference2DeleteDelTwo bodies \ No newline at end of file diff --git a/docs/ux/mockups/rich__bodies_2__reference.svg b/docs/ux/mockups/rich__bodies_2__reference.svg new file mode 100644 index 0000000000..1bfbac0db0 --- /dev/null +++ b/docs/ux/mockups/rich__bodies_2__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsMeasureInterferenceTwo bodies · Reference \ No newline at end of file diff --git a/docs/ux/mockups/rich__body_sheet.svg b/docs/ux/mockups/rich__body_sheet.svg new file mode 100644 index 0000000000..a1cc27808d --- /dev/null +++ b/docs/ux/mockups/rich__body_sheet.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sheet body selected — pick what to do with itWorking document · 8 slotsThicken SurfaceSurface OffsetMoveShift+YMeasureModify3Sheet body \ No newline at end of file diff --git a/docs/ux/mockups/rich__body_sheet__modify.svg b/docs/ux/mockups/rich__body_sheet__modify.svg new file mode 100644 index 0000000000..7ce8dbee54 --- /dev/null +++ b/docs/ux/mockups/rich__body_sheet__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsColourDeleteDelEditSheet body · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__body_solid.svg b/docs/ux/mockups/rich__body_solid.svg new file mode 100644 index 0000000000..e958532347 --- /dev/null +++ b/docs/ux/mockups/rich__body_solid.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Solid body selected — pick what to do with itWorking document · 8 slotsRemove3Dress-up2Repeat3MoveShift+YReference3Modify3Solid body \ No newline at end of file diff --git a/docs/ux/mockups/rich__body_solid__dressup.svg b/docs/ux/mockups/rich__body_solid__dressup.svg new file mode 100644 index 0000000000..7a9ceed334 --- /dev/null +++ b/docs/ux/mockups/rich__body_solid__dressup.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Dress-up — pick oneWorking document · 8 slotsFilletShift+FChamferSolid body · Dress-up \ No newline at end of file diff --git a/docs/ux/mockups/rich__body_solid__modify.svg b/docs/ux/mockups/rich__body_solid__modify.svg new file mode 100644 index 0000000000..7a6340d40f --- /dev/null +++ b/docs/ux/mockups/rich__body_solid__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsColourDeleteDelEditSolid body · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__body_solid__reference.svg b/docs/ux/mockups/rich__body_solid__reference.svg new file mode 100644 index 0000000000..27639836c6 --- /dev/null +++ b/docs/ux/mockups/rich__body_solid__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsMassProjectMeasureSolid body · Reference \ No newline at end of file diff --git a/docs/ux/mockups/rich__body_solid__remove.svg b/docs/ux/mockups/rich__body_solid__remove.svg new file mode 100644 index 0000000000..edbddb7115 --- /dev/null +++ b/docs/ux/mockups/rich__body_solid__remove.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Remove — pick oneWorking document · 8 slotsShellShift+KCutShift+XSplitSolid body · Remove \ No newline at end of file diff --git a/docs/ux/mockups/rich__body_solid__repeat.svg b/docs/ux/mockups/rich__body_solid__repeat.svg new file mode 100644 index 0000000000..74dd67c7de --- /dev/null +++ b/docs/ux/mockups/rich__body_solid__repeat.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Repeat — pick oneWorking document · 8 slotsPatternShift+NMirrorShift+ZPattern on CurveSolid body · Repeat \ No newline at end of file diff --git a/docs/ux/mockups/rich__coordsys.svg b/docs/ux/mockups/rich__coordsys.svg new file mode 100644 index 0000000000..8cef106106 --- /dev/null +++ b/docs/ux/mockups/rich__coordsys.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Coordinate system selected — pick what to do with itWorking document · 8 slotsMateModify2Coordinate system \ No newline at end of file diff --git a/docs/ux/mockups/rich__coordsys__modify.svg b/docs/ux/mockups/rich__coordsys__modify.svg new file mode 100644 index 0000000000..92eb28d3dc --- /dev/null +++ b/docs/ux/mockups/rich__coordsys__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsDeleteDelEditCoordinate system · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__datum_axis.svg b/docs/ux/mockups/rich__datum_axis.svg new file mode 100644 index 0000000000..c9da648ab7 --- /dev/null +++ b/docs/ux/mockups/rich__datum_axis.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Datum axis selected — pick what to do with itWorking document · 8 slotsModify2Datum axis \ No newline at end of file diff --git a/docs/ux/mockups/rich__datum_axis__modify.svg b/docs/ux/mockups/rich__datum_axis__modify.svg new file mode 100644 index 0000000000..fd0ae80c52 --- /dev/null +++ b/docs/ux/mockups/rich__datum_axis__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsDeleteDelEditDatum axis · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__datum_plane.svg b/docs/ux/mockups/rich__datum_plane.svg new file mode 100644 index 0000000000..8ef88bd9a3 --- /dev/null +++ b/docs/ux/mockups/rich__datum_plane.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Datum plane selected — pick what to do with itWorking document · 8 slotsSketchShift+SRemove2MirrorShift+ZReference3Modify2Datum plane \ No newline at end of file diff --git a/docs/ux/mockups/rich__datum_plane__modify.svg b/docs/ux/mockups/rich__datum_plane__modify.svg new file mode 100644 index 0000000000..39e5cad41e --- /dev/null +++ b/docs/ux/mockups/rich__datum_plane__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsDeleteDelEditDatum plane · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__datum_plane__reference.svg b/docs/ux/mockups/rich__datum_plane__reference.svg new file mode 100644 index 0000000000..bae3119b6b --- /dev/null +++ b/docs/ux/mockups/rich__datum_plane__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsProjectPlaneShift+PHelixDatum plane · Reference \ No newline at end of file diff --git a/docs/ux/mockups/rich__datum_plane__remove.svg b/docs/ux/mockups/rich__datum_plane__remove.svg new file mode 100644 index 0000000000..c98b33ad31 --- /dev/null +++ b/docs/ux/mockups/rich__datum_plane__remove.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Remove — pick oneWorking document · 8 slotsHoleShift+HCutShift+XDatum plane · Remove \ No newline at end of file diff --git a/docs/ux/mockups/rich__edge_circ.svg b/docs/ux/mockups/rich__edge_circ.svg new file mode 100644 index 0000000000..1d07291623 --- /dev/null +++ b/docs/ux/mockups/rich__edge_circ.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Circular edge selected — pick what to do with itWorking document · 8 slotsThreadShift+TDress-up2MeasureCircular edge \ No newline at end of file diff --git a/docs/ux/mockups/rich__edge_circ__dressup.svg b/docs/ux/mockups/rich__edge_circ__dressup.svg new file mode 100644 index 0000000000..b315fc2e22 --- /dev/null +++ b/docs/ux/mockups/rich__edge_circ__dressup.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Dress-up — pick oneWorking document · 8 slotsFilletShift+FChamferCircular edge · Dress-up \ No newline at end of file diff --git a/docs/ux/mockups/rich__edge_str.svg b/docs/ux/mockups/rich__edge_str.svg new file mode 100644 index 0000000000..2c41ce74fc --- /dev/null +++ b/docs/ux/mockups/rich__edge_str.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Straight edge selected — pick what to do with itWorking document · 8 slotsDress-up2Pattern on CurveReference3Straight edge \ No newline at end of file diff --git a/docs/ux/mockups/rich__edge_str__dressup.svg b/docs/ux/mockups/rich__edge_str__dressup.svg new file mode 100644 index 0000000000..8e674c044f --- /dev/null +++ b/docs/ux/mockups/rich__edge_str__dressup.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Dress-up — pick oneWorking document · 8 slotsFilletShift+FChamferStraight edge · Dress-up \ No newline at end of file diff --git a/docs/ux/mockups/rich__edge_str__reference.svg b/docs/ux/mockups/rich__edge_str__reference.svg new file mode 100644 index 0000000000..bc99ca6a13 --- /dev/null +++ b/docs/ux/mockups/rich__edge_str__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsMeasurePlaneShift+PAxisShift+AStraight edge · Reference \ No newline at end of file diff --git a/docs/ux/mockups/rich__face_cyl.svg b/docs/ux/mockups/rich__face_cyl.svg new file mode 100644 index 0000000000..3c2860373f --- /dev/null +++ b/docs/ux/mockups/rich__face_cyl.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Cylindrical face selected — pick what to do with itWorking document · 8 slotsThreadShift+TReference3Modify2Cylindrical face \ No newline at end of file diff --git a/docs/ux/mockups/rich__face_cyl__modify.svg b/docs/ux/mockups/rich__face_cyl__modify.svg new file mode 100644 index 0000000000..9f573682ad --- /dev/null +++ b/docs/ux/mockups/rich__face_cyl__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsDelete FaceEditCylindrical face · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__face_cyl__reference.svg b/docs/ux/mockups/rich__face_cyl__reference.svg new file mode 100644 index 0000000000..a62be81de8 --- /dev/null +++ b/docs/ux/mockups/rich__face_cyl__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsMeasureAxisShift+AHelixCylindrical face · Reference \ No newline at end of file diff --git a/docs/ux/mockups/rich__face_other.svg b/docs/ux/mockups/rich__face_other.svg new file mode 100644 index 0000000000..e5cff4eee5 --- /dev/null +++ b/docs/ux/mockups/rich__face_other.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Curved face selected — pick what to do with itWorking document · 8 slotsThickenDraftShift+DMeasureModify2Curved face \ No newline at end of file diff --git a/docs/ux/mockups/rich__face_other__modify.svg b/docs/ux/mockups/rich__face_other__modify.svg new file mode 100644 index 0000000000..8b5fcfd63f --- /dev/null +++ b/docs/ux/mockups/rich__face_other__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsDelete FaceEditCurved face · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__face_planar.svg b/docs/ux/mockups/rich__face_planar.svg new file mode 100644 index 0000000000..5a58e2fb72 --- /dev/null +++ b/docs/ux/mockups/rich__face_planar.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Planar face selected — pick what to do with itWorking document · 8 slotsSketchShift+SAdd material2Remove2Dress-up3PatternShift+NTransform2Reference5Modify2Planar face \ No newline at end of file diff --git a/docs/ux/mockups/rich__face_planar__add.svg b/docs/ux/mockups/rich__face_planar__add.svg new file mode 100644 index 0000000000..82acc85038 --- /dev/null +++ b/docs/ux/mockups/rich__face_planar__add.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Add material — pick oneWorking document · 8 slotsExtrudeShift+EThickenPlanar face · Add material \ No newline at end of file diff --git a/docs/ux/mockups/rich__face_planar__dressup.svg b/docs/ux/mockups/rich__face_planar__dressup.svg new file mode 100644 index 0000000000..8d32b9f212 --- /dev/null +++ b/docs/ux/mockups/rich__face_planar__dressup.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Dress-up — pick oneWorking document · 8 slotsFilletShift+FChamferDraftShift+DPlanar face · Dress-up \ No newline at end of file diff --git a/docs/ux/mockups/rich__face_planar__modify.svg b/docs/ux/mockups/rich__face_planar__modify.svg new file mode 100644 index 0000000000..bffd218131 --- /dev/null +++ b/docs/ux/mockups/rich__face_planar__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsDelete FaceEditPlanar face · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__face_planar__reference.svg b/docs/ux/mockups/rich__face_planar__reference.svg new file mode 100644 index 0000000000..4682f1e7b1 --- /dev/null +++ b/docs/ux/mockups/rich__face_planar__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsCoord SysShift+CProjectMeasurePlaneShift+PAxisShift+APlanar face · Reference \ No newline at end of file diff --git a/docs/ux/mockups/rich__face_planar__remove.svg b/docs/ux/mockups/rich__face_planar__remove.svg new file mode 100644 index 0000000000..b77a5a0c50 --- /dev/null +++ b/docs/ux/mockups/rich__face_planar__remove.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Remove — pick oneWorking document · 8 slotsHoleShift+HShellShift+KPlanar face · Remove \ No newline at end of file diff --git a/docs/ux/mockups/rich__face_planar__transform.svg b/docs/ux/mockups/rich__face_planar__transform.svg new file mode 100644 index 0000000000..2e27983c8b --- /dev/null +++ b/docs/ux/mockups/rich__face_planar__transform.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Transform — pick oneWorking document · 8 slotsMateAlign toPlanar face · Transform \ No newline at end of file diff --git a/docs/ux/mockups/rich__none.svg b/docs/ux/mockups/rich__none.svg new file mode 100644 index 0000000000..4e8a9dc640 --- /dev/null +++ b/docs/ux/mockups/rich__none.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Click a face or a reference plane, then a toolWorking document · 8 slotsSketchShift+SReference4Nothing selected \ No newline at end of file diff --git a/docs/ux/mockups/rich__none__reference.svg b/docs/ux/mockups/rich__none__reference.svg new file mode 100644 index 0000000000..14c47c4b27 --- /dev/null +++ b/docs/ux/mockups/rich__none__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsCoord SysShift+CHelixPlaneShift+PAxisShift+ANothing selected · Reference \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_2ent.svg b/docs/ux/mockups/rich__sk_2ent.svg new file mode 100644 index 0000000000..738b01ecf2 --- /dev/null +++ b/docs/ux/mockups/rich__sk_2ent.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Two sketch entities selected — pick what to do with itWorking document · 8 slotsCreate9OffsetOTrimTDress-up2MirrorMMoveReference3Modify2Two sketch entities \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_2ent__create.svg b/docs/ux/mockups/rich__sk_2ent__create.svg new file mode 100644 index 0000000000..6d27ffa34a --- /dev/null +++ b/docs/ux/mockups/rich__sk_2ent__create.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Create — pick oneWorking document · 8 slotsLineLRectangleRCircleCArcASlotSEllipseESplineBMore2Two sketch entities · Create \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_2ent__dressup.svg b/docs/ux/mockups/rich__sk_2ent__dressup.svg new file mode 100644 index 0000000000..929520b8d2 --- /dev/null +++ b/docs/ux/mockups/rich__sk_2ent__dressup.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Dress-up — pick oneWorking document · 8 slotsFilletFChamferHTwo sketch entities · Dress-up \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_2ent__modify.svg b/docs/ux/mockups/rich__sk_2ent__modify.svg new file mode 100644 index 0000000000..d8be7c2d4f --- /dev/null +++ b/docs/ux/mockups/rich__sk_2ent__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsDeleteDelExtendXTwo sketch entities · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_2ent__reference.svg b/docs/ux/mockups/rich__sk_2ent__reference.svg new file mode 100644 index 0000000000..9ffc2592a8 --- /dev/null +++ b/docs/ux/mockups/rich__sk_2ent__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsConstructionQDimensionDConstrainKTwo sketch entities · Reference \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_arc.svg b/docs/ux/mockups/rich__sk_arc.svg new file mode 100644 index 0000000000..d470369f1a --- /dev/null +++ b/docs/ux/mockups/rich__sk_arc.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch arc or circle selected — pick what to do with itWorking document · 8 slotsCreate9OffsetOTrimTMirrorMMoveReference3Modify2Sketch arc or circle \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_arc__create.svg b/docs/ux/mockups/rich__sk_arc__create.svg new file mode 100644 index 0000000000..1f901596ec --- /dev/null +++ b/docs/ux/mockups/rich__sk_arc__create.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Create — pick oneWorking document · 8 slotsLineLRectangleRCircleCArcASlotSEllipseESplineBMore2Sketch arc or circle · Create \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_arc__modify.svg b/docs/ux/mockups/rich__sk_arc__modify.svg new file mode 100644 index 0000000000..52f9d7d3e5 --- /dev/null +++ b/docs/ux/mockups/rich__sk_arc__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsDeleteDelExtendXSketch arc or circle · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_arc__reference.svg b/docs/ux/mockups/rich__sk_arc__reference.svg new file mode 100644 index 0000000000..53e949c184 --- /dev/null +++ b/docs/ux/mockups/rich__sk_arc__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsConstructionQDimensionDConstrainKSketch arc or circle · Reference \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_line.svg b/docs/ux/mockups/rich__sk_line.svg new file mode 100644 index 0000000000..4ca4000d59 --- /dev/null +++ b/docs/ux/mockups/rich__sk_line.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch line selected — pick what to do with itWorking document · 8 slotsCreate9OffsetOTrimTDress-up2MirrorMMoveReference3Modify2Sketch line \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_line__create.svg b/docs/ux/mockups/rich__sk_line__create.svg new file mode 100644 index 0000000000..c37f2d0e45 --- /dev/null +++ b/docs/ux/mockups/rich__sk_line__create.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Create — pick oneWorking document · 8 slotsLineLRectangleRCircleCArcASlotSEllipseESplineBMore2Sketch line · Create \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_line__dressup.svg b/docs/ux/mockups/rich__sk_line__dressup.svg new file mode 100644 index 0000000000..29e86762d2 --- /dev/null +++ b/docs/ux/mockups/rich__sk_line__dressup.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Dress-up — pick oneWorking document · 8 slotsFilletFChamferHSketch line · Dress-up \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_line__modify.svg b/docs/ux/mockups/rich__sk_line__modify.svg new file mode 100644 index 0000000000..b9775b7d94 --- /dev/null +++ b/docs/ux/mockups/rich__sk_line__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsDeleteDelExtendXSketch line · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_line__reference.svg b/docs/ux/mockups/rich__sk_line__reference.svg new file mode 100644 index 0000000000..6eb1ef621f --- /dev/null +++ b/docs/ux/mockups/rich__sk_line__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsConstructionQDimensionDConstrainKSketch line · Reference \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_loop.svg b/docs/ux/mockups/rich__sk_loop.svg new file mode 100644 index 0000000000..c07d1c09c3 --- /dev/null +++ b/docs/ux/mockups/rich__sk_loop.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Closed sketch loop selected — pick what to do with itWorking document · 8 slotsAdd material8PatternShift+NModify2Closed sketch loop \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_loop__add.svg b/docs/ux/mockups/rich__sk_loop__add.svg new file mode 100644 index 0000000000..bf9f429b81 --- /dev/null +++ b/docs/ux/mockups/rich__sk_loop__add.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Add material — pick oneWorking document · 8 slotsSurface FillExtrudeShift+ERevolveShift+RSweepShift+WLoftShift+LSurface ExtrudeShift+GSurface RevolveSurface LoftClosed sketch loop · Add material \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_loop__modify.svg b/docs/ux/mockups/rich__sk_loop__modify.svg new file mode 100644 index 0000000000..c466379c9e --- /dev/null +++ b/docs/ux/mockups/rich__sk_loop__modify.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Modify — pick oneWorking document · 8 slotsDeleteDelEditClosed sketch loop · Modify \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_none.svg b/docs/ux/mockups/rich__sk_none.svg new file mode 100644 index 0000000000..ffe49ab9a0 --- /dev/null +++ b/docs/ux/mockups/rich__sk_none.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch, nothing picked selected — pick what to do with itWorking document · 8 slotsCreate9Reference2Sketch, nothing picked \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_none__create.svg b/docs/ux/mockups/rich__sk_none__create.svg new file mode 100644 index 0000000000..c9a2bc698d --- /dev/null +++ b/docs/ux/mockups/rich__sk_none__create.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Create — pick oneWorking document · 8 slotsLineLRectangleRCircleCArcASlotSEllipseESplineBMore2Sketch, nothing picked · Create \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_none__reference.svg b/docs/ux/mockups/rich__sk_none__reference.svg new file mode 100644 index 0000000000..cc9d465fa4 --- /dev/null +++ b/docs/ux/mockups/rich__sk_none__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsDimensionDConstructionQSketch, nothing picked · Reference \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_point.svg b/docs/ux/mockups/rich__sk_point.svg new file mode 100644 index 0000000000..f089787bca --- /dev/null +++ b/docs/ux/mockups/rich__sk_point.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch point selected — pick what to do with itWorking document · 8 slotsCreate9MoveReference2DeleteDelSketch point \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_point__create.svg b/docs/ux/mockups/rich__sk_point__create.svg new file mode 100644 index 0000000000..5d2070a6c5 --- /dev/null +++ b/docs/ux/mockups/rich__sk_point__create.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Create — pick oneWorking document · 8 slotsLineLRectangleRCircleCArcASlotSEllipseESplineBMore2Sketch point · Create \ No newline at end of file diff --git a/docs/ux/mockups/rich__sk_point__reference.svg b/docs/ux/mockups/rich__sk_point__reference.svg new file mode 100644 index 0000000000..e090382a24 --- /dev/null +++ b/docs/ux/mockups/rich__sk_point__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsDimensionDConstrainKSketch point · Reference \ No newline at end of file diff --git a/docs/ux/mockups/rich__vertex.svg b/docs/ux/mockups/rich__vertex.svg new file mode 100644 index 0000000000..f37bbd7d47 --- /dev/null +++ b/docs/ux/mockups/rich__vertex.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Vertex selected — pick what to do with itWorking document · 8 slotsReference4Vertex \ No newline at end of file diff --git a/docs/ux/mockups/rich__vertex__reference.svg b/docs/ux/mockups/rich__vertex__reference.svg new file mode 100644 index 0000000000..ceabba032e --- /dev/null +++ b/docs/ux/mockups/rich__vertex__reference.svg @@ -0,0 +1 @@ +PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsCoord SysShift+CMeasurePlaneShift+PAxisShift+AVertex · Reference \ No newline at end of file diff --git a/docs/ux/offer_atlas.html b/docs/ux/offer_atlas.html new file mode 100644 index 0000000000..13ef9beac3 --- /dev/null +++ b/docs/ux/offer_atlas.html @@ -0,0 +1,68 @@ +Design tab — offer atlas + +
+

The offer — atlas of every state

+

Every state of the object-driven tool offer, generated from + docs/ux/tool_atlas.json. The invariant under test: a verb has one address, that + address is the same in every selection where it appears, and slots that do not apply are drawn + empty rather than compacted.

+
+
60verbs mapped
+
20selection kinds
+
40primary rings
+
73secondary rings
+
113states total
+
3.5/8mean slots filled
+
6verbs with no GUI yet
+
+
+
+

Decision 1 — ring capacity

+

The same three selections at eight and at twelve. Eight keeps 45° between neighbours, which is + the reliable eyes-free pointing threshold and maps 1:1 to the numpad; twelve buys direct addresses + for more verbs at 30° spacing and positions that stop being nameable.

+
8 slots — face_planar
8 slots — edge_str
8 slots — sk_line
+
12 slots — face_planar
12 slots — edge_str
12 slots — sk_line
+ +

Decision 2 — one map or one per mode

+

These renders use ONE shared map: sketch verbs occupy the same eight families as model verbs, + so dress-up is south-east whether you picked a solid edge or a sketch line. Compare the sketch-mode + states below against the model-mode ones — if a verb that exists in both modes ever appears at two + addresses, the shared map has failed and the split map is the answer.

+ +

The matrix — every selection, every document state

+
+ + +
SelectionDocumentVerbsSlots2nd ringsWhat lands where
Nothing selectedWorking document52/81create: Sketch · reference: Plane, Axis, Coord Sys, Helix
Planar faceWorking document188/86create: Sketch · add: Extrude, Thicken · remove: Hole, Shell · dressup: Fillet, Chamfer, Draft · repeat: Pattern · transform: Mate, Align to · reference: Plane, Axis, Coord Sys, Project, Measure · modify: Edit, Delete Face
Cylindrical faceWorking document63/82remove: Thread · reference: Axis, Helix, Measure · modify: Edit, Delete Face
Curved faceWorking document54/81add: Thicken · dressup: Draft · reference: Measure · modify: Edit, Delete Face
Straight edgeWorking document63/82dressup: Fillet, Chamfer · repeat: Pattern on Curve · reference: Plane, Axis, Measure
Circular edgeWorking document43/81remove: Thread · dressup: Fillet, Chamfer · reference: Measure
VertexWorking document41/81reference: Plane, Axis, Coord Sys, Measure
Solid bodyWorking document156/85remove: Shell, Cut, Split · dressup: Fillet, Chamfer · repeat: Pattern, Mirror, Pattern on Curve · transform: Move · reference: Project, Measure, Mass · modify: Edit, Colour, Delete
Sheet bodyWorking document75/81add: Thicken Surface · dressup: Surface Offset · transform: Move · reference: Measure · modify: Edit, Colour, Delete
Two bodiesWorking document54/81add: Combine · transform: Mate · reference: Measure, Interference · modify: Delete
Datum planeWorking document95/83create: Sketch · remove: Hole, Cut · repeat: Mirror · reference: Plane, Helix, Project · modify: Edit, Delete
Datum axisWorking document21/81modify: Edit, Delete
Coordinate systemWorking document32/81transform: Mate · modify: Edit, Delete
Text / imported artWorking document43/81repeat: Pattern · transform: Move · modify: Edit, Delete
Closed sketch loopWorking document113/82add: Extrude, Revolve, Sweep, Loft, Surface Extrude, Surface Revolve, Surface Loft, Surface Fill · repeat: Pattern · modify: Edit, Delete
Sketch, nothing pickedWorking document112/82create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · reference: Dimension, Construction
Sketch lineWorking document208/84create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · add: Offset · remove: Trim · dressup: Fillet, Chamfer · repeat: Mirror · transform: Move · reference: Dimension, Constrain, Construction · modify: Extend, Delete
Sketch arc or circleWorking document187/83create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · add: Offset · remove: Trim · repeat: Mirror · transform: Move · reference: Dimension, Constrain, Construction · modify: Extend, Delete
Sketch pointWorking document134/82create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · transform: Move · reference: Dimension, Constrain · modify: Delete
Two sketch entitiesWorking document208/84create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · add: Offset · remove: Trim · dressup: Fillet, Chamfer · repeat: Mirror · transform: Move · reference: Dimension, Constrain, Construction · modify: Extend, Delete
Nothing selectedFresh document52/81create: Sketch · reference: Plane, Axis, Coord Sys, Helix
Planar faceFresh document74/81create: Sketch · add: Extrude · reference: Plane, Axis, Coord Sys, Measure · modify: Edit
Cylindrical faceFresh document42/81reference: Axis, Helix, Measure · modify: Edit
Curved faceFresh document22/80reference: Measure · modify: Edit
Straight edgeFresh document31/81reference: Plane, Axis, Measure
Circular edgeFresh document11/80reference: Measure
VertexFresh document41/81reference: Plane, Axis, Coord Sys, Measure
Solid bodyFresh document32/81reference: Measure · modify: Edit, Delete
Sheet bodyFresh document32/81reference: Measure · modify: Edit, Delete
Two bodiesFresh document22/80reference: Measure · modify: Delete
Datum planeFresh document53/82create: Sketch · reference: Plane, Helix · modify: Edit, Delete
Datum axisFresh document21/81modify: Edit, Delete
Coordinate systemFresh document21/81modify: Edit, Delete
Text / imported artFresh document21/81modify: Edit, Delete
Closed sketch loopFresh document72/82add: Extrude, Revolve, Surface Extrude, Surface Revolve, Surface Fill · modify: Edit, Delete
Sketch, nothing pickedFresh document112/82create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · reference: Dimension, Construction
Sketch lineFresh document208/84create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · add: Offset · remove: Trim · dressup: Fillet, Chamfer · repeat: Mirror · transform: Move · reference: Dimension, Constrain, Construction · modify: Extend, Delete
Sketch arc or circleFresh document187/83create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · add: Offset · remove: Trim · repeat: Mirror · transform: Move · reference: Dimension, Constrain, Construction · modify: Extend, Delete
Sketch pointFresh document134/82create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · transform: Move · reference: Dimension, Constrain · modify: Delete
Two sketch entitiesFresh document208/84create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · add: Offset · remove: Trim · dressup: Fillet, Chamfer · repeat: Mirror · transform: Move · reference: Dimension, Constrain, Construction · modify: Extend, Delete
+ +

Overflow — the one place eight slots is not enough

+

Measured, not predicted: the create sub-ring needs 10 addresses, so Polygon, Point are pushed behind a “More” slot. This is the decision the ring size actually turns on — either a verb moves to another family, or the tail goes to a third level, or the ring is not eight. It affects sketch mode only; every model-mode family fits.

+ +

Not in the offer

+

Import STEP, Import mesh, Text, SVG, Export STEP, Commit to Plate, Undo, Redo, Variables, Section view, Origin planes, World axes — these act on the document, not on a selection, + so they stay in chrome. Verbs with kernel support but no GUI today, which still hold an address: + Split, Pattern on Curve, Align to, Measure, Mass, Interference.

+ +

All states

+
Nothing selected — Working document
Nothing selected — Working document
Nothing selected — Reference ring
Nothing selected — Reference ring
Planar face — Working document
Planar face — Working document
Planar face — Add material ring
Planar face — Add material ring
Planar face — Remove ring
Planar face — Remove ring
Planar face — Dress-up ring
Planar face — Dress-up ring
Planar face — Transform ring
Planar face — Transform ring
Planar face — Reference ring
Planar face — Reference ring
Planar face — Modify ring
Planar face — Modify ring
Cylindrical face — Working document
Cylindrical face — Working document
Cylindrical face — Reference ring
Cylindrical face — Reference ring
Cylindrical face — Modify ring
Cylindrical face — Modify ring
Curved face — Working document
Curved face — Working document
Curved face — Modify ring
Curved face — Modify ring
Straight edge — Working document
Straight edge — Working document
Straight edge — Dress-up ring
Straight edge — Dress-up ring
Straight edge — Reference ring
Straight edge — Reference ring
Circular edge — Working document
Circular edge — Working document
Circular edge — Dress-up ring
Circular edge — Dress-up ring
Vertex — Working document
Vertex — Working document
Vertex — Reference ring
Vertex — Reference ring
Solid body — Working document
Solid body — Working document
Solid body — Remove ring
Solid body — Remove ring
Solid body — Dress-up ring
Solid body — Dress-up ring
Solid body — Repeat ring
Solid body — Repeat ring
Solid body — Reference ring
Solid body — Reference ring
Solid body — Modify ring
Solid body — Modify ring
Sheet body — Working document
Sheet body — Working document
Sheet body — Modify ring
Sheet body — Modify ring
Two bodies — Working document
Two bodies — Working document
Two bodies — Reference ring
Two bodies — Reference ring
Datum plane — Working document
Datum plane — Working document
Datum plane — Remove ring
Datum plane — Remove ring
Datum plane — Reference ring
Datum plane — Reference ring
Datum plane — Modify ring
Datum plane — Modify ring
Datum axis — Working document
Datum axis — Working document
Datum axis — Modify ring
Datum axis — Modify ring
Coordinate system — Working document
Coordinate system — Working document
Coordinate system — Modify ring
Coordinate system — Modify ring
Text / imported art — Working document
Text / imported art — Working document
Text / imported art — Modify ring
Text / imported art — Modify ring
Closed sketch loop — Working document
Closed sketch loop — Working document
Closed sketch loop — Add material ring
Closed sketch loop — Add material ring
Closed sketch loop — Modify ring
Closed sketch loop — Modify ring
Sketch, nothing picked — Working document
Sketch, nothing picked — Working document
Sketch, nothing picked — Create ring
Sketch, nothing picked — Create ring
Sketch, nothing picked — Reference ring
Sketch, nothing picked — Reference ring
Sketch line — Working document
Sketch line — Working document
Sketch line — Create ring
Sketch line — Create ring
Sketch line — Dress-up ring
Sketch line — Dress-up ring
Sketch line — Reference ring
Sketch line — Reference ring
Sketch line — Modify ring
Sketch line — Modify ring
Sketch arc or circle — Working document
Sketch arc or circle — Working document
Sketch arc or circle — Create ring
Sketch arc or circle — Create ring
Sketch arc or circle — Reference ring
Sketch arc or circle — Reference ring
Sketch arc or circle — Modify ring
Sketch arc or circle — Modify ring
Sketch point — Working document
Sketch point — Working document
Sketch point — Create ring
Sketch point — Create ring
Sketch point — Reference ring
Sketch point — Reference ring
Two sketch entities — Working document
Two sketch entities — Working document
Two sketch entities — Create ring
Two sketch entities — Create ring
Two sketch entities — Dress-up ring
Two sketch entities — Dress-up ring
Two sketch entities — Reference ring
Two sketch entities — Reference ring
Two sketch entities — Modify ring
Two sketch entities — Modify ring
Nothing selected — Fresh document
Nothing selected — Fresh document
Nothing selected — Reference ring
Nothing selected — Reference ring
Planar face — Fresh document
Planar face — Fresh document
Planar face — Reference ring
Planar face — Reference ring
Cylindrical face — Fresh document
Cylindrical face — Fresh document
Cylindrical face — Reference ring
Cylindrical face — Reference ring
Curved face — Fresh document
Curved face — Fresh document
Straight edge — Fresh document
Straight edge — Fresh document
Straight edge — Reference ring
Straight edge — Reference ring
Circular edge — Fresh document
Circular edge — Fresh document
Vertex — Fresh document
Vertex — Fresh document
Vertex — Reference ring
Vertex — Reference ring
Solid body — Fresh document
Solid body — Fresh document
Solid body — Modify ring
Solid body — Modify ring
Sheet body — Fresh document
Sheet body — Fresh document
Sheet body — Modify ring
Sheet body — Modify ring
Two bodies — Fresh document
Two bodies — Fresh document
Datum plane — Fresh document
Datum plane — Fresh document
Datum plane — Reference ring
Datum plane — Reference ring
Datum plane — Modify ring
Datum plane — Modify ring
Datum axis — Fresh document
Datum axis — Fresh document
Datum axis — Modify ring
Datum axis — Modify ring
Coordinate system — Fresh document
Coordinate system — Fresh document
Coordinate system — Modify ring
Coordinate system — Modify ring
Text / imported art — Fresh document
Text / imported art — Fresh document
Text / imported art — Modify ring
Text / imported art — Modify ring
Closed sketch loop — Fresh document
Closed sketch loop — Fresh document
Closed sketch loop — Add material ring
Closed sketch loop — Add material ring
Closed sketch loop — Modify ring
Closed sketch loop — Modify ring
Sketch, nothing picked — Fresh document
Sketch, nothing picked — Fresh document
Sketch, nothing picked — Create ring
Sketch, nothing picked — Create ring
Sketch, nothing picked — Reference ring
Sketch, nothing picked — Reference ring
Sketch line — Fresh document
Sketch line — Fresh document
Sketch line — Create ring
Sketch line — Create ring
Sketch line — Dress-up ring
Sketch line — Dress-up ring
Sketch line — Reference ring
Sketch line — Reference ring
Sketch line — Modify ring
Sketch line — Modify ring
Sketch arc or circle — Fresh document
Sketch arc or circle — Fresh document
Sketch arc or circle — Create ring
Sketch arc or circle — Create ring
Sketch arc or circle — Reference ring
Sketch arc or circle — Reference ring
Sketch arc or circle — Modify ring
Sketch arc or circle — Modify ring
Sketch point — Fresh document
Sketch point — Fresh document
Sketch point — Create ring
Sketch point — Create ring
Sketch point — Reference ring
Sketch point — Reference ring
Two sketch entities — Fresh document
Two sketch entities — Fresh document
Two sketch entities — Create ring
Two sketch entities — Create ring
Two sketch entities — Dress-up ring
Two sketch entities — Dress-up ring
Two sketch entities — Reference ring
Two sketch entities — Reference ring
Two sketch entities — Modify ring
Two sketch entities — Modify ring
+
diff --git a/docs/ux/offer_atlas_inline.html b/docs/ux/offer_atlas_inline.html new file mode 100644 index 0000000000..51f7b28f61 --- /dev/null +++ b/docs/ux/offer_atlas_inline.html @@ -0,0 +1,67 @@ +Design tab — offer atlas + +
+

The offer — atlas of every state

+

Every state of the object-driven tool offer, generated from + docs/ux/tool_atlas.json. The invariant under test: a verb has one address, that + address is the same in every selection where it appears, and slots that do not apply are drawn + empty rather than compacted.

+
+
60verbs mapped
+
20selection kinds
+
40primary rings
+
73secondary rings
+
113states total
+
3.5/8mean slots filled
+
6verbs with no GUI yet
+
+
+
+

Decision 1 — ring capacity

+

The same three selections at eight and at twelve. Eight keeps 45° between neighbours, which is + the reliable eyes-free pointing threshold and maps 1:1 to the numpad; twelve buys direct addresses + for more verbs at 30° spacing and positions that stop being nameable.

+
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Planar face selected — pick what to do with itWorking document · 8 slotsSketchShift+SAdd material2Remove2Dress-up3PatternShift+NTransform2Reference5Modify2Planar face
8 slots — face_planar
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Straight edge selected — pick what to do with itWorking document · 8 slotsDress-up2Pattern on CurveReference3Straight edge
8 slots — edge_str
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch line selected — pick what to do with itWorking document · 8 slotsCreate9OffsetOTrimTDress-up2MirrorMMoveReference3Modify2Sketch line
8 slots — sk_line
+
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Planar face selected — pick what to do with itWorking document · 12 slotsSketchShift+SAdd material2Remove2Dress-up3PatternShift+NTransform2Reference5Modify2Planar face
12 slots — face_planar
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Straight edge selected — pick what to do with itWorking document · 12 slotsDress-up2Pattern on CurveReference3Straight edge
12 slots — edge_str
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch line selected — pick what to do with itWorking document · 12 slotsCreate9OffsetOTrimTDress-up2MirrorMMoveReference3Modify2Sketch line
12 slots — sk_line
+ +

Decision 2 — one map or one per mode

+

These renders use ONE shared map: sketch verbs occupy the same eight families as model verbs, + so dress-up is south-east whether you picked a solid edge or a sketch line. Compare the sketch-mode + states below against the model-mode ones — if a verb that exists in both modes ever appears at two + addresses, the shared map has failed and the split map is the answer.

+ +

The matrix — every selection, every document state

+
+ + +
SelectionDocumentVerbsSlots2nd ringsWhat lands where
Nothing selectedWorking document52/81create: Sketch · reference: Plane, Axis, Coord Sys, Helix
Planar faceWorking document188/86create: Sketch · add: Extrude, Thicken · remove: Hole, Shell · dressup: Fillet, Chamfer, Draft · repeat: Pattern · transform: Mate, Align to · reference: Plane, Axis, Coord Sys, Project, Measure · modify: Edit, Delete Face
Cylindrical faceWorking document63/82remove: Thread · reference: Axis, Helix, Measure · modify: Edit, Delete Face
Curved faceWorking document54/81add: Thicken · dressup: Draft · reference: Measure · modify: Edit, Delete Face
Straight edgeWorking document63/82dressup: Fillet, Chamfer · repeat: Pattern on Curve · reference: Plane, Axis, Measure
Circular edgeWorking document43/81remove: Thread · dressup: Fillet, Chamfer · reference: Measure
VertexWorking document41/81reference: Plane, Axis, Coord Sys, Measure
Solid bodyWorking document156/85remove: Shell, Cut, Split · dressup: Fillet, Chamfer · repeat: Pattern, Mirror, Pattern on Curve · transform: Move · reference: Project, Measure, Mass · modify: Edit, Colour, Delete
Sheet bodyWorking document75/81add: Thicken Surface · dressup: Surface Offset · transform: Move · reference: Measure · modify: Edit, Colour, Delete
Two bodiesWorking document54/81add: Combine · transform: Mate · reference: Measure, Interference · modify: Delete
Datum planeWorking document95/83create: Sketch · remove: Hole, Cut · repeat: Mirror · reference: Plane, Helix, Project · modify: Edit, Delete
Datum axisWorking document21/81modify: Edit, Delete
Coordinate systemWorking document32/81transform: Mate · modify: Edit, Delete
Text / imported artWorking document43/81repeat: Pattern · transform: Move · modify: Edit, Delete
Closed sketch loopWorking document113/82add: Extrude, Revolve, Sweep, Loft, Surface Extrude, Surface Revolve, Surface Loft, Surface Fill · repeat: Pattern · modify: Edit, Delete
Sketch, nothing pickedWorking document112/82create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · reference: Dimension, Construction
Sketch lineWorking document208/84create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · add: Offset · remove: Trim · dressup: Fillet, Chamfer · repeat: Mirror · transform: Move · reference: Dimension, Constrain, Construction · modify: Extend, Delete
Sketch arc or circleWorking document187/83create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · add: Offset · remove: Trim · repeat: Mirror · transform: Move · reference: Dimension, Constrain, Construction · modify: Extend, Delete
Sketch pointWorking document134/82create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · transform: Move · reference: Dimension, Constrain · modify: Delete
Two sketch entitiesWorking document208/84create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · add: Offset · remove: Trim · dressup: Fillet, Chamfer · repeat: Mirror · transform: Move · reference: Dimension, Constrain, Construction · modify: Extend, Delete
Nothing selectedFresh document52/81create: Sketch · reference: Plane, Axis, Coord Sys, Helix
Planar faceFresh document74/81create: Sketch · add: Extrude · reference: Plane, Axis, Coord Sys, Measure · modify: Edit
Cylindrical faceFresh document42/81reference: Axis, Helix, Measure · modify: Edit
Curved faceFresh document22/80reference: Measure · modify: Edit
Straight edgeFresh document31/81reference: Plane, Axis, Measure
Circular edgeFresh document11/80reference: Measure
VertexFresh document41/81reference: Plane, Axis, Coord Sys, Measure
Solid bodyFresh document32/81reference: Measure · modify: Edit, Delete
Sheet bodyFresh document32/81reference: Measure · modify: Edit, Delete
Two bodiesFresh document22/80reference: Measure · modify: Delete
Datum planeFresh document53/82create: Sketch · reference: Plane, Helix · modify: Edit, Delete
Datum axisFresh document21/81modify: Edit, Delete
Coordinate systemFresh document21/81modify: Edit, Delete
Text / imported artFresh document21/81modify: Edit, Delete
Closed sketch loopFresh document72/82add: Extrude, Revolve, Surface Extrude, Surface Revolve, Surface Fill · modify: Edit, Delete
Sketch, nothing pickedFresh document112/82create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · reference: Dimension, Construction
Sketch lineFresh document208/84create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · add: Offset · remove: Trim · dressup: Fillet, Chamfer · repeat: Mirror · transform: Move · reference: Dimension, Constrain, Construction · modify: Extend, Delete
Sketch arc or circleFresh document187/83create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · add: Offset · remove: Trim · repeat: Mirror · transform: Move · reference: Dimension, Constrain, Construction · modify: Extend, Delete
Sketch pointFresh document134/82create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · transform: Move · reference: Dimension, Constrain · modify: Delete
Two sketch entitiesFresh document208/84create: Line, Rectangle, Circle, Arc, Slot, Ellipse, Spline, Polygon, Point · add: Offset · remove: Trim · dressup: Fillet, Chamfer · repeat: Mirror · transform: Move · reference: Dimension, Constrain, Construction · modify: Extend, Delete
+ +

Overflow — the one place eight slots is not enough

+

Measured, not predicted: the create sub-ring needs 10 addresses, so Polygon, Point are pushed behind a “More” slot. This is the decision the ring size actually turns on — either a verb moves to another family, or the tail goes to a third level, or the ring is not eight. It affects sketch mode only; every model-mode family fits.

+ +

Not in the offer

+

Import STEP, Import mesh, Text, SVG, Export STEP, Commit to Plate, Undo, Redo, Variables, Section view, Origin planes, World axes — these act on the document, not on a selection, + so they stay in chrome. Verbs with kernel support but no GUI today, which still hold an address: + Split, Pattern on Curve, Align to, Measure, Mass, Interference.

+ +

The states

+
PreparePreviewDesignFEATURESnothing yetClick a face or a reference plane, then a toolFresh document · 8 slotsSketchShift+SReference4Nothing selected
Fresh document, nothing selected — the first-run picture
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Click a face or a reference plane, then a toolWorking document · 8 slotsSketchShift+SReference4Nothing selected
Nothing selected
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Planar face selected — pick what to do with itWorking document · 8 slotsSketchShift+SAdd material2Remove2Dress-up3PatternShift+NTransform2Reference5Modify2Planar face
Planar face
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Cylindrical face selected — pick what to do with itWorking document · 8 slotsThreadShift+TReference3Modify2Cylindrical face
Cylindrical face
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Curved face selected — pick what to do with itWorking document · 8 slotsThickenDraftShift+DMeasureModify2Curved face
Curved face
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Straight edge selected — pick what to do with itWorking document · 8 slotsDress-up2Pattern on CurveReference3Straight edge
Straight edge
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Circular edge selected — pick what to do with itWorking document · 8 slotsThreadShift+TDress-up2MeasureCircular edge
Circular edge
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Vertex selected — pick what to do with itWorking document · 8 slotsReference4Vertex
Vertex
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Solid body selected — pick what to do with itWorking document · 8 slotsRemove3Dress-up2Repeat3MoveShift+YReference3Modify3Solid body
Solid body
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sheet body selected — pick what to do with itWorking document · 8 slotsThicken SurfaceSurface OffsetMoveShift+YMeasureModify3Sheet body
Sheet body
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Two bodies selected — pick what to do with itWorking document · 8 slotsCombineShift+BMateReference2DeleteDelTwo bodies
Two bodies
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Datum plane selected — pick what to do with itWorking document · 8 slotsSketchShift+SRemove2MirrorShift+ZReference3Modify2Datum plane
Datum plane
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Datum axis selected — pick what to do with itWorking document · 8 slotsModify2Datum axis
Datum axis
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Coordinate system selected — pick what to do with itWorking document · 8 slotsMateModify2Coordinate system
Coordinate system
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Text / imported art selected — pick what to do with itWorking document · 8 slotsABCPatternShift+NMoveShift+YModify2Text / imported art
Text / imported art
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Closed sketch loop selected — pick what to do with itWorking document · 8 slotsAdd material8PatternShift+NModify2Closed sketch loop
Closed sketch loop
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch, nothing picked selected — pick what to do with itWorking document · 8 slotsCreate9Reference2Sketch, nothing picked
Sketch, nothing picked
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch line selected — pick what to do with itWorking document · 8 slotsCreate9OffsetOTrimTDress-up2MirrorMMoveReference3Modify2Sketch line
Sketch line
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch arc or circle selected — pick what to do with itWorking document · 8 slotsCreate9OffsetOTrimTMirrorMMoveReference3Modify2Sketch arc or circle
Sketch arc or circle
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch point selected — pick what to do with itWorking document · 8 slotsCreate9MoveReference2DeleteDelSketch point
Sketch point
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Two sketch entities selected — pick what to do with itWorking document · 8 slotsCreate9OffsetOTrimTDress-up2MirrorMMoveReference3Modify2Two sketch entities
Two sketch entities
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Add material — pick oneWorking document · 8 slotsExtrudeShift+EThickenPlanar face · Add material
Planar face · Add material sub-ring
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Reference — pick oneWorking document · 8 slotsCoord SysShift+CProjectMeasurePlaneShift+PAxisShift+APlanar face · Reference
Planar face · Reference sub-ring
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Create — pick oneWorking document · 8 slotsLineLRectangleRCircleCArcASlotSEllipseESplineBMore2Sketch, nothing picked · Create
Sketch · Create sub-ring (the overflow case)
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Remove — pick oneWorking document · 8 slotsShellShift+KCutShift+XSplitSolid body · Remove
Solid body · Remove sub-ring
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Planar face selected — pick what to do with itWorking document · 8 slotsSketchShift+SAdd material2Remove2Dress-up3PatternShift+NTransform2Reference5Modify2Planar face
8 slots — planar face
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Planar face selected — pick what to do with itWorking document · 12 slotsSketchShift+SAdd material2Remove2Dress-up3PatternShift+NTransform2Reference5Modify2Planar face
12 slots — planar face
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch line selected — pick what to do with itWorking document · 8 slotsCreate9OffsetOTrimTDress-up2MirrorMMoveReference3Modify2Sketch line
8 slots — sketch line
PreparePreviewDesignFEATURESSketch1Extrude1Hole1Fillet1Sketch2Extrude2Sketch line selected — pick what to do with itWorking document · 12 slotsCreate9OffsetOTrimTDress-up2MirrorMMoveReference3Modify2Sketch line
12 slots — sketch line
diff --git a/docs/ux/tool_atlas.json b/docs/ux/tool_atlas.json new file mode 100644 index 0000000000..3ede7c175e --- /dev/null +++ b/docs/ux/tool_atlas.json @@ -0,0 +1,220 @@ +{ + "_comment": [ + "Source of truth for the object-driven tool offer (see docs/cad_ux_guidelines.md 4.1).", + "Every verb, the selections it accepts, the document state it needs, and its fixed", + "compass address. Extracted from the code, not from memory:", + " verbs + shortcuts + refusal messages -> src/slic3r/GUI/DesignPanel.cpp (feat_dropdown", + " call sites at 524/662/734/790/874/904, sk_key table at 369-400, m_keys_feature)", + " kernel coverage -> src/libslic3r/CadDocument.hpp (enum CadFeatureType)", + " headless coverage -> src/slic3r/GUI/McpControl.cpp (method == \"...\")", + " selection kinds -> src/slic3r/GUI/DesignCanvas.hpp (the on_*_selected callbacks)", + "gen_offer_mockups.py reads this file; the eventual C++ offer table is generated from it", + "too, so the map exists once." + ], + + "slots": [ + {"id": "create", "pos": "N", "angle": 270, "label": "Create", "why": "makes new geometry from nothing you have yet"}, + {"id": "add", "pos": "NE", "angle": 315, "label": "Add material", "why": "grows solid or sheet material"}, + {"id": "remove", "pos": "E", "angle": 0, "label": "Remove", "why": "takes material away"}, + {"id": "dressup", "pos": "SE", "angle": 45, "label": "Dress-up", "why": "finishes faces and edges without changing the shape's intent"}, + {"id": "repeat", "pos": "S", "angle": 90, "label": "Repeat", "why": "copies what exists"}, + {"id": "transform", "pos": "SW", "angle": 135, "label": "Transform", "why": "moves without changing shape"}, + {"id": "reference", "pos": "W", "angle": 180, "label": "Reference", "why": "makes datums, curves and measurements"}, + {"id": "modify", "pos": "NW", "angle": 225, "label": "Modify", "why": "edits or removes what is already there"} + ], + + "selections": [ + {"id": "none", "name": "Nothing selected", "mode": "model", "shape": "empty"}, + {"id": "face_planar", "name": "Planar face", "mode": "model", "shape": "box_top"}, + {"id": "face_cyl", "name": "Cylindrical face", "mode": "model", "shape": "box_bore"}, + {"id": "face_other", "name": "Curved face", "mode": "model", "shape": "box_fillet_face"}, + {"id": "edge_str", "name": "Straight edge", "mode": "model", "shape": "box_edge"}, + {"id": "edge_circ", "name": "Circular edge", "mode": "model", "shape": "box_bore_rim"}, + {"id": "vertex", "name": "Vertex", "mode": "model", "shape": "box_vertex"}, + {"id": "body_solid", "name": "Solid body", "mode": "model", "shape": "box_whole"}, + {"id": "body_sheet", "name": "Sheet body", "mode": "model", "shape": "sheet"}, + {"id": "bodies_2", "name": "Two bodies", "mode": "model", "shape": "two_boxes"}, + {"id": "datum_plane", "name": "Datum plane", "mode": "model", "shape": "datum"}, + {"id": "datum_axis", "name": "Datum axis", "mode": "model", "shape": "axis"}, + {"id": "coordsys", "name": "Coordinate system", "mode": "model", "shape": "csys"}, + {"id": "art", "name": "Text / imported art","mode": "model", "shape": "art"}, + {"id": "sk_loop", "name": "Closed sketch loop", "mode": "model", "shape": "loop"}, + {"id": "sk_none", "name": "Sketch, nothing picked", "mode": "sketch", "shape": "sk_empty"}, + {"id": "sk_line", "name": "Sketch line", "mode": "sketch", "shape": "sk_line"}, + {"id": "sk_arc", "name": "Sketch arc or circle","mode": "sketch","shape": "sk_arc"}, + {"id": "sk_point", "name": "Sketch point", "mode": "sketch", "shape": "sk_point"}, + {"id": "sk_2ent", "name": "Two sketch entities","mode": "sketch", "shape": "sk_two"} + ], + + "doc_states": [ + {"id": "rich", "name": "Working document", "bodies": 2, "sketches": 2, "sheet": true, + "note": "two solids, two sketches, one sheet body — everything doc-gated is legal"}, + {"id": "fresh", "name": "Fresh document", "bodies": 0, "sketches": 0, "sheet": false, + "note": "nothing built yet — shows how much of the ring is empty on first open"} + ], + + "verbs": [ + {"id": "sketch", "name": "Sketch", "slot": "create", "key": "Shift+S", "feature": "Sketch", "mcp": null, + "accepts": ["face_planar", "datum_plane", "none"], "needs": {}, + "refusal": "Click a face or a reference plane in the viewport, then a sketch tool", "gui": true}, + + {"id": "extrude", "name": "Extrude", "slot": "add", "key": "Shift+E", "feature": "Extrude", "mcp": "extrude", + "accepts": ["sk_loop", "face_planar"], "needs": {}, + "refusal": "Create a sketch, or pick a solid face, first", "gui": true}, + {"id": "revolve", "name": "Revolve", "slot": "add", "key": "Shift+R", "feature": "Revolve", "mcp": "revolve", + "accepts": ["sk_loop"], "needs": {}, + "refusal": "Create a sketch profile to revolve first", "gui": true}, + {"id": "sweep", "name": "Sweep", "slot": "add", "key": "Shift+W", "feature": "Sweep", "mcp": null, + "accepts": ["sk_loop"], "needs": {"sketches": 2}, + "refusal": "Create a profile sketch to sweep first", "gui": true}, + {"id": "loft", "name": "Loft", "slot": "add", "key": "Shift+L", "feature": "Loft", "mcp": null, + "accepts": ["sk_loop"], "needs": {"sketches": 2}, + "refusal": "Create at least two profile sketches to loft", "gui": true}, + {"id": "thicken", "name": "Thicken", "slot": "add", "key": null, "feature": "Thicken", "mcp": "thicken", + "accepts": ["face_planar", "face_other"], "needs": {"bodies": 1}, + "refusal": "Thicken needs a solid body — add or import one first", "gui": true}, + {"id": "rib", "name": "Rib", "slot": "add", "key": null, "feature": "Rib", "mcp": "rib", + "accepts": ["sk_line"], "needs": {"bodies": 1}, + "refusal": "Rib needs a solid body — add or import one first", "gui": true}, + {"id": "boolean", "name": "Combine", "slot": "add", "key": "Shift+B", "feature": "Boolean", "mcp": "boolean", + "accepts": ["bodies_2"], "needs": {"bodies": 2}, + "refusal": "Boolean needs two bodies — create or import a second solid", "gui": true}, + {"id": "surf_extrude", "name": "Surface Extrude", "slot": "add", "key": "Shift+G", "feature": "SurfaceExtrude","mcp": "surface_extrude", + "accepts": ["sk_loop"], "needs": {}, "refusal": "Create a sketch first", "gui": true}, + {"id": "surf_revolve", "name": "Surface Revolve", "slot": "add", "key": null, "feature": "SurfaceRevolve","mcp": "surface_revolve", + "accepts": ["sk_loop"], "needs": {}, "refusal": "Create a sketch profile to revolve first", "gui": true}, + {"id": "surf_loft", "name": "Surface Loft", "slot": "add", "key": null, "feature": "SurfaceLoft", "mcp": "surface_loft", + "accepts": ["sk_loop"], "needs": {"sketches": 2}, "refusal": "Create at least two profile sketches to loft", "gui": true}, + {"id": "surf_fill", "name": "Surface Fill", "slot": "add", "key": null, "feature": "SurfaceFill", "mcp": "surface_fill", + "accepts": ["sk_loop"], "needs": {}, "refusal": "Create a closed sketch first", "gui": true}, + {"id": "thicken_surf", "name": "Thicken Surface", "slot": "add", "key": null, "feature": "ThickenSurface","mcp": "thicken_surface", + "accepts": ["body_sheet"], "needs": {"sheet": true}, "refusal": "target is not a sheet body", "gui": true}, + + {"id": "hole", "name": "Hole", "slot": "remove", "key": "Shift+H", "feature": "Hole", "mcp": "hole", + "accepts": ["face_planar", "datum_plane"], "needs": {"bodies": 1}, + "refusal": "Pick a face or a plane to drill into", "gui": true}, + {"id": "thread", "name": "Thread", "slot": "remove", "key": "Shift+T", "feature": "Thread", "mcp": null, + "accepts": ["face_cyl", "edge_circ"], "needs": {"bodies": 1}, + "refusal": "Pick a cylindrical surface (bore / outer) or a circular edge for a thread", "gui": true}, + {"id": "shell", "name": "Shell", "slot": "remove", "key": "Shift+K", "feature": "Shell", "mcp": "shell", + "accepts": ["face_planar", "body_solid"], "needs": {"bodies": 1}, + "refusal": "Shell needs a solid body", "gui": true}, + {"id": "cut", "name": "Cut", "slot": "remove", "key": "Shift+X", "feature": "Cut", "mcp": null, + "accepts": ["body_solid", "datum_plane"], "needs": {"bodies": 1}, + "refusal": "Create a solid body to cut first", "gui": true}, + {"id": "split", "name": "Split", "slot": "remove", "key": null, "feature": "Cut", "mcp": "split", + "accepts": ["body_solid"], "needs": {"bodies": 1}, "refusal": "Split needs a solid body", "gui": false}, + + {"id": "fillet", "name": "Fillet", "slot": "dressup", "key": "Shift+F", "feature": "Fillet", "mcp": "fillet", + "accepts": ["edge_str", "edge_circ", "face_planar", "body_solid"], "needs": {"bodies": 1}, + "refusal": "Pick an edge to round", "gui": true}, + {"id": "chamfer", "name": "Chamfer", "slot": "dressup", "key": null, "feature": "Chamfer", "mcp": "chamfer", + "accepts": ["edge_str", "edge_circ", "face_planar", "body_solid"], "needs": {"bodies": 1}, + "refusal": "Pick an edge to bevel", "gui": true}, + {"id": "draft", "name": "Draft", "slot": "dressup", "key": "Shift+D", "feature": "Draft", "mcp": "draft", + "accepts": ["face_planar", "face_other"], "needs": {"bodies": 1}, + "refusal": "Pick a face to taper", "gui": true}, + {"id": "surf_offset", "name": "Surface Offset", "slot": "dressup", "key": null, "feature": "SurfaceOffset", "mcp": "surface_offset", + "accepts": ["body_sheet"], "needs": {"sheet": true}, "refusal": "target is not a sheet body", "gui": true}, + + {"id": "pattern", "name": "Pattern", "slot": "repeat", "key": "Shift+N", "feature": "Pattern", "mcp": "pattern", + "accepts": ["body_solid", "face_planar", "sk_loop", "art"], "needs": {"bodies": 1}, + "refusal": "Create a solid body to pattern first", "gui": true}, + {"id": "mirror", "name": "Mirror", "slot": "repeat", "key": "Shift+Z", "feature": "Mirror", "mcp": "mirror", + "accepts": ["body_solid", "datum_plane"], "needs": {"bodies": 1}, + "refusal": "Mirror needs a body — add or import one first", "gui": true}, + {"id": "pat_curve", "name": "Pattern on Curve","slot": "repeat", "key": null, "feature": "Pattern", "mcp": "pattern_on_curve", + "accepts": ["body_solid", "edge_str"], "needs": {"bodies": 1}, + "refusal": "Pattern on curve needs a body and a curve", "gui": false}, + + {"id": "transform", "name": "Move", "slot": "transform", "key": "Shift+Y", "feature": "Transform", "mcp": "transform", + "accepts": ["body_solid", "body_sheet", "art"], "needs": {"bodies": 1}, + "refusal": "Transform needs a body — add or import one first", "gui": true}, + {"id": "mate", "name": "Mate", "slot": "transform", "key": null, "feature": "Mate", "mcp": "mate", + "accepts": ["coordsys", "bodies_2", "face_planar"], "needs": {"bodies": 2}, + "refusal": "A mate needs two coordinate systems", "gui": true}, + {"id": "align", "name": "Align to", "slot": "transform", "key": null, "feature": "Transform", "mcp": "transform", + "accepts": ["face_planar"], "needs": {"bodies": 1}, "refusal": "Align needs a body", "gui": false}, + + {"id": "plane", "name": "Plane", "slot": "reference", "key": "Shift+P", "feature": "Plane", "mcp": null, + "accepts": ["none", "face_planar", "edge_str", "datum_plane", "vertex"], "needs": {}, + "refusal": null, "gui": true}, + {"id": "axis", "name": "Axis", "slot": "reference", "key": "Shift+A", "feature": "Axis", "mcp": "axis", + "accepts": ["none", "face_planar", "face_cyl", "edge_str", "vertex"], "needs": {}, + "refusal": null, "gui": true}, + {"id": "coordsys_v", "name": "Coord Sys", "slot": "reference", "key": "Shift+C", "feature": "CoordSys", "mcp": "coordsys", + "accepts": ["none", "face_planar", "vertex"], "needs": {}, "refusal": null, "gui": true}, + {"id": "helix", "name": "Helix", "slot": "reference", "key": null, "feature": "Helix", "mcp": "helix", + "accepts": ["none", "datum_plane", "face_cyl"], "needs": {}, "refusal": null, "gui": true}, + {"id": "project", "name": "Project", "slot": "reference", "key": null, "feature": "Project", "mcp": "project", + "accepts": ["body_solid", "face_planar", "datum_plane"], "needs": {"bodies": 1}, + "refusal": "Project needs a body — add or import one first", "gui": true}, + {"id": "measure", "name": "Measure", "slot": "reference", "key": null, "feature": null, "mcp": "measure", + "accepts": ["face_planar", "face_cyl", "face_other", "edge_str", "edge_circ", "vertex", "body_solid", "body_sheet", "bodies_2", "sk_line", "sk_arc", "sk_2ent"], + "needs": {}, "refusal": null, "gui": false}, + {"id": "mass_props", "name": "Mass", "slot": "reference", "key": null, "feature": null, "mcp": "mass_properties", + "accepts": ["body_solid"], "needs": {"bodies": 1}, "refusal": null, "gui": false}, + {"id": "interference", "name": "Interference", "slot": "reference", "key": null, "feature": null, "mcp": "check_interference", + "accepts": ["bodies_2"], "needs": {"bodies": 2}, "refusal": null, "gui": false}, + + {"id": "edit_feature", "name": "Edit", "slot": "modify", "key": null, "feature": null, "mcp": "set_feature_expr", + "accepts": ["body_solid", "face_planar", "face_cyl", "face_other", "sk_loop", "art", "datum_plane", "datum_axis", "coordsys", "body_sheet"], + "needs": {}, "refusal": null, "gui": true}, + {"id": "delete_face", "name": "Delete Face", "slot": "modify", "key": null, "feature": "DeleteFace", "mcp": "delete_face", + "accepts": ["face_planar", "face_cyl", "face_other"], "needs": {"bodies": 1}, + "refusal": "Delete Face needs a body — add or import one first", "gui": true}, + {"id": "colour", "name": "Colour", "slot": "modify", "key": null, "feature": null, "mcp": null, + "accepts": ["body_solid", "body_sheet"], "needs": {"bodies": 1}, "refusal": null, "gui": true}, + {"id": "delete", "name": "Delete", "slot": "modify", "key": "Del", "feature": null, "mcp": null, + "accepts": ["body_solid", "body_sheet", "sk_loop", "art", "datum_plane", "datum_axis", "coordsys", "bodies_2", "sk_line", "sk_arc", "sk_point", "sk_2ent"], + "needs": {}, "refusal": null, "gui": true}, + + {"id": "sk_line_t", "name": "Line", "slot": "create", "key": "L", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_none", "sk_point", "sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_rect", "name": "Rectangle", "slot": "create", "key": "R", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_none", "sk_point", "sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_circle", "name": "Circle", "slot": "create", "key": "C", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_none", "sk_point", "sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_arc_t", "name": "Arc", "slot": "create", "key": "A", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_none", "sk_point", "sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_slot", "name": "Slot", "slot": "create", "key": "S", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_none", "sk_point", "sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_ellipse", "name": "Ellipse", "slot": "create", "key": "E", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_none", "sk_point", "sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_spline", "name": "Spline", "slot": "create", "key": "B", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_none", "sk_point", "sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_polygon", "name": "Polygon", "slot": "create", "key": "G", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_none", "sk_point", "sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_point_t", "name": "Point", "slot": "create", "key": "P", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_none", "sk_point", "sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + + {"id": "sk_offset", "name": "Offset", "slot": "add", "key": "O", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_trim", "name": "Trim", "slot": "remove", "key": "T", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_fillet", "name": "Fillet", "slot": "dressup", "key": "F", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_line", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_chamfer", "name": "Chamfer", "slot": "dressup", "key": "H", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_line", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_mirror", "name": "Mirror", "slot": "repeat", "key": "M", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_move", "name": "Move", "slot": "transform", "key": null, "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_line", "sk_arc", "sk_point", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_dimension", "name": "Dimension", "slot": "reference", "key": "D", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_none", "sk_line", "sk_arc", "sk_point", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_constrain", "name": "Constrain", "slot": "reference", "key": "K", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_line", "sk_arc", "sk_point", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_construct", "name": "Construction", "slot": "reference", "key": "Q", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_none", "sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_extend", "name": "Extend", "slot": "modify", "key": "X", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_line", "sk_arc", "sk_2ent"], "needs": {}, "refusal": null, "gui": true}, + {"id": "sk_delete", "name": "Delete", "slot": "modify", "key": "Del", "feature": "Sketch", "mcp": null, "mode": "sketch", + "accepts": ["sk_line", "sk_arc", "sk_point", "sk_2ent"], "needs": {}, "refusal": null, "gui": true} + ], + + "chrome_only": { + "_why": "document-level actions act on the DOCUMENT, not on a selection, so they stay in chrome and never enter the offer (see 4.1)", + "items": ["Import STEP", "Import mesh", "Text", "SVG", "Export STEP", "Commit to Plate", + "Undo", "Redo", "Variables", "Section view", "Origin planes", "World axes"] + } +}