From 85c6d59a342fc61fd779ded3b708c77cc2af3c3c Mon Sep 17 00:00:00 2001 From: skarakovski Date: Sun, 8 Nov 2026 23:08:07 +0700 Subject: [PATCH] openspec: add editor polish series 44a-44h --- openspec/ROADMAP.md | 10 +++- openspec/changes/44a-storybook/.openspec.yaml | 2 + openspec/changes/44a-storybook/design.md | 31 ++++++++++++ openspec/changes/44a-storybook/proposal.md | 30 ++++++++++++ .../specs/component-catalog/spec.md | 46 ++++++++++++++++++ openspec/changes/44a-storybook/tasks.md | 33 +++++++++++++ .../.openspec.yaml | 2 + .../44b-editor-viewport-navigation/design.md | 48 +++++++++++++++++++ .../proposal.md | 31 ++++++++++++ .../specs/editor-sketch/spec.md | 33 +++++++++++++ .../specs/model-viewport/spec.md | 29 +++++++++++ .../44b-editor-viewport-navigation/tasks.md | 30 ++++++++++++ .../.openspec.yaml | 2 + .../44c-editor-sketch-input-face/design.md | 44 +++++++++++++++++ .../44c-editor-sketch-input-face/proposal.md | 35 ++++++++++++++ .../specs/editor-sketch-features/spec.md | 37 ++++++++++++++ .../specs/editor-sketch/spec.md | 29 +++++++++++ .../44c-editor-sketch-input-face/tasks.md | 28 +++++++++++ .../.openspec.yaml | 2 + .../44d-editor-layout-workbenches/design.md | 37 ++++++++++++++ .../44d-editor-layout-workbenches/proposal.md | 34 +++++++++++++ .../specs/editor-workspace/spec.md | 29 +++++++++++ .../44d-editor-layout-workbenches/tasks.md | 26 ++++++++++ .../44e-editor-context-menu/.openspec.yaml | 2 + .../changes/44e-editor-context-menu/design.md | 41 ++++++++++++++++ .../44e-editor-context-menu/proposal.md | 34 +++++++++++++ .../specs/editor-context-menu/spec.md | 43 +++++++++++++++++ .../specs/editor-workspace/spec.md | 33 +++++++++++++ .../changes/44e-editor-context-menu/tasks.md | 26 ++++++++++ .../44f-editor-op-preview/.openspec.yaml | 2 + .../changes/44f-editor-op-preview/design.md | 32 +++++++++++++ .../changes/44f-editor-op-preview/proposal.md | 31 ++++++++++++ .../specs/editor-op-preview/spec.md | 35 ++++++++++++++ .../changes/44f-editor-op-preview/tasks.md | 26 ++++++++++ .../44g-editor-split-panel/.openspec.yaml | 2 + .../changes/44g-editor-split-panel/design.md | 31 ++++++++++++ .../44g-editor-split-panel/proposal.md | 38 +++++++++++++++ .../specs/editor-cut-connectors/spec.md | 25 ++++++++++ .../specs/editor-plane-cut/spec.md | 29 +++++++++++ .../changes/44g-editor-split-panel/tasks.md | 27 +++++++++++ .../.openspec.yaml | 2 + .../44h-editor-mesh-repair-wizard/design.md | 38 +++++++++++++++ .../44h-editor-mesh-repair-wizard/proposal.md | 39 +++++++++++++++ .../specs/editor-mesh-health/spec.md | 33 +++++++++++++ .../specs/editor-mesh-repair/spec.md | 29 +++++++++++ .../44h-editor-mesh-repair-wizard/tasks.md | 27 +++++++++++ .../45-editor-project-default/proposal.md | 2 +- 47 files changed, 1253 insertions(+), 2 deletions(-) create mode 100644 openspec/changes/44a-storybook/.openspec.yaml create mode 100644 openspec/changes/44a-storybook/design.md create mode 100644 openspec/changes/44a-storybook/proposal.md create mode 100644 openspec/changes/44a-storybook/specs/component-catalog/spec.md create mode 100644 openspec/changes/44a-storybook/tasks.md create mode 100644 openspec/changes/44b-editor-viewport-navigation/.openspec.yaml create mode 100644 openspec/changes/44b-editor-viewport-navigation/design.md create mode 100644 openspec/changes/44b-editor-viewport-navigation/proposal.md create mode 100644 openspec/changes/44b-editor-viewport-navigation/specs/editor-sketch/spec.md create mode 100644 openspec/changes/44b-editor-viewport-navigation/specs/model-viewport/spec.md create mode 100644 openspec/changes/44b-editor-viewport-navigation/tasks.md create mode 100644 openspec/changes/44c-editor-sketch-input-face/.openspec.yaml create mode 100644 openspec/changes/44c-editor-sketch-input-face/design.md create mode 100644 openspec/changes/44c-editor-sketch-input-face/proposal.md create mode 100644 openspec/changes/44c-editor-sketch-input-face/specs/editor-sketch-features/spec.md create mode 100644 openspec/changes/44c-editor-sketch-input-face/specs/editor-sketch/spec.md create mode 100644 openspec/changes/44c-editor-sketch-input-face/tasks.md create mode 100644 openspec/changes/44d-editor-layout-workbenches/.openspec.yaml create mode 100644 openspec/changes/44d-editor-layout-workbenches/design.md create mode 100644 openspec/changes/44d-editor-layout-workbenches/proposal.md create mode 100644 openspec/changes/44d-editor-layout-workbenches/specs/editor-workspace/spec.md create mode 100644 openspec/changes/44d-editor-layout-workbenches/tasks.md create mode 100644 openspec/changes/44e-editor-context-menu/.openspec.yaml create mode 100644 openspec/changes/44e-editor-context-menu/design.md create mode 100644 openspec/changes/44e-editor-context-menu/proposal.md create mode 100644 openspec/changes/44e-editor-context-menu/specs/editor-context-menu/spec.md create mode 100644 openspec/changes/44e-editor-context-menu/specs/editor-workspace/spec.md create mode 100644 openspec/changes/44e-editor-context-menu/tasks.md create mode 100644 openspec/changes/44f-editor-op-preview/.openspec.yaml create mode 100644 openspec/changes/44f-editor-op-preview/design.md create mode 100644 openspec/changes/44f-editor-op-preview/proposal.md create mode 100644 openspec/changes/44f-editor-op-preview/specs/editor-op-preview/spec.md create mode 100644 openspec/changes/44f-editor-op-preview/tasks.md create mode 100644 openspec/changes/44g-editor-split-panel/.openspec.yaml create mode 100644 openspec/changes/44g-editor-split-panel/design.md create mode 100644 openspec/changes/44g-editor-split-panel/proposal.md create mode 100644 openspec/changes/44g-editor-split-panel/specs/editor-cut-connectors/spec.md create mode 100644 openspec/changes/44g-editor-split-panel/specs/editor-plane-cut/spec.md create mode 100644 openspec/changes/44g-editor-split-panel/tasks.md create mode 100644 openspec/changes/44h-editor-mesh-repair-wizard/.openspec.yaml create mode 100644 openspec/changes/44h-editor-mesh-repair-wizard/design.md create mode 100644 openspec/changes/44h-editor-mesh-repair-wizard/proposal.md create mode 100644 openspec/changes/44h-editor-mesh-repair-wizard/specs/editor-mesh-health/spec.md create mode 100644 openspec/changes/44h-editor-mesh-repair-wizard/specs/editor-mesh-repair/spec.md create mode 100644 openspec/changes/44h-editor-mesh-repair-wizard/tasks.md diff --git a/openspec/ROADMAP.md b/openspec/ROADMAP.md index dd71606..7ad3895 100644 --- a/openspec/ROADMAP.md +++ b/openspec/ROADMAP.md @@ -59,7 +59,15 @@ | 42 | `42-editor-mesh-repair` | 41 | v1.13.0. Диагностика и ремонт STL, QEM децимация (meshoptimizer) с фиксацией вершин, сглаживание MLS с сохранением рёбер >30°, BVH raycasting (three-mesh-bvh), карта толщины стенок, кисть выделения граней, Lay on Face, измерения | | 43 | `43-editor-cut-split` | 41, 42 | v1.14.0. Plane Cut (меш и твердотельный), Split на стол с соединителями (шипы, штифты, магниты, ласточкин хвост), мастер отверстий (Hole tool: винты, втулки, магниты), нарезка винтовой резьбы (Thread tool: метрическая/дюймовая) и текст на грани | | 44 | `44-editor-face-tools` | 41, 42 | v1.15.0. Топологическое именование (FaceFingerprint, EdgeFingerprint), выбор граней/рёбер (CAD box select: window/crossing), контекстные плашки в 3D (HUD Context Chips), Push/Pull, точные 3D Fillet/Chamfer рёбер, эскиз на грани с проекцией рёбер | -| 45 | `45-editor-project-default` | 43, 44 | v2.0.0 (major: `/` ведёт в редактор, выбор генераторов переезжает на `/generators`). Файл проекта `.pkit` (ZIP: scene.json + сетки + эскизы + 3D-пины/заметки, защита ZipSlip), кольцевой буфер автосохранения, редактор — вход по умолчанию, генераторы как вставляемые объекты (Send to Editor / Edit in generator) | +| 44a | `44a-storybook` | 44 | v1.15.1. Storybook 8 для библиотеки компонентов: `src/ui/`, токены `theme.css`, декораторы i18n (EN/RU) и единиц (мм/дюйм), smoke-тест | +| 44b | `44b-editor-viewport-navigation` | 44 | v1.16.0. Адаптивная сетка FreeCAD 5×5 (3D и эскиз), синхронизация кривой зума эскиза с OrbitControls, разделение Shift+Drag (панорамирование) и рамки выделения | +| 44c | `44c-editor-sketch-input-face` | 44b | v1.17.0. Поля HUD ввода координат для окружностей (центр X, Y, диаметр/радиус) и точек, бесшовный пайплайн «эскиз на грани ➔ выдавливание (Join/Cut)» | +| 44d | `44d-editor-layout-workbenches` | 44a, 44c | v1.18.0. Единый компактный хедер редактора, разделение верстаков Model / Sketch, симметричные сайдбары 280px с ручкой изменения ширины | +| 44e | `44e-editor-context-menu` | 44c, 44d | v1.19.0. Универсальное контекстное меню (ПКМ) во вьюпорте (объекты, пустое поле, грани, ребра) и на холсте эскиза | +| 44f | `44f-editor-op-preview` | 44d | v1.20.0. Полупрозрачный фантомный предпросмотр операций (Extrude, Revolve, Cut, Push/Pull) прямо во вьюпорте в процессе настройки | +| 44g | `44g-editor-split-panel` | 44d, 44f | v1.20.1. Перенос «Разрезать по столу» из модального окна в боковую панель инструмента с 3D-плоскостями разреза и предпросмотром стола | +| 44h | `44h-editor-mesh-repair-wizard` | 44a, 44d | v1.21.0. Инспекция и ремонт STL по референсу MeshDoc: визуализация дефектных ребер на модели, отчет До/После с дельтами, расчет веса филамента | +| 45 | `45-editor-project-default` | 44h | v2.0.0 (major: `/` ведёт в редактор, выбор генераторов переезжает на `/generators`). Файл проекта `.pkit` (ZIP: scene.json + сетки + эскизы + 3D-пины/заметки, защита ZipSlip), кольцевой буфер автосохранения, редактор — вход по умолчанию, генераторы как вставляемые объекты (Send to Editor / Edit in generator) | | 46 | `46-editor-step-cad` | 45 | v2.1.0. Обмен данными CAD: экспорт тел в точный формат STEP (AP203/214/242) для CAD и слайсеров (Bambu/Prusa/Orca), импорт STEP-файлов в дерево операций, валидация замкнутости и сшивка | | 47 | `47-editor-sweep-loft` | 44, 46 | v2.2.0. Кинематические операции твердотельного моделирования: Sweep (протягивание профиля по траектории), Loft (переход между произвольными сечениями) и Draft (литейный уклон граней) | diff --git a/openspec/changes/44a-storybook/.openspec.yaml b/openspec/changes/44a-storybook/.openspec.yaml new file mode 100644 index 0000000..c0ad5ed --- /dev/null +++ b/openspec/changes/44a-storybook/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-11-08 diff --git a/openspec/changes/44a-storybook/design.md b/openspec/changes/44a-storybook/design.md new file mode 100644 index 0000000..7b0f98a --- /dev/null +++ b/openspec/changes/44a-storybook/design.md @@ -0,0 +1,31 @@ +# Design: Component Catalog (Storybook) + +## Context +PrintKit is a client-only React 19 + TypeScript app with Tailwind CSS v4, Tabler Icons, and i18next. Its UI design is documented across static HTML artboards in `design/artboards/`. As the editor workspace expands with complex panels, floating toolbars, and contextual dialogs, testing components in isolation becomes necessary to prevent regressions and accelerate UI iteration. + +## Goals +- Add Storybook 8 with `@storybook/react-vite` sharing the root `vite.config.ts` plugins and CSS. +- Provide global decorators for i18n (`en`/`ru`) and `UnitProvider` (`mm`/`in`). +- Include stories for all `src/ui/` primitives and core editor shell components with mock data. +- Ensure automated verification via portable stories in Vitest so stories never rot. + +## Non-Goals +- Visual snapshot regression services (Chromatic, Percy). +- Three.js WebGL viewport story (Viewport is heavy and requires WebGL context; container mocks are used instead). + +## Decisions + +### Decision 1: Storybook 8 with `@storybook/react-vite` +We use `@storybook/react-vite` configured in `.storybook/main.ts`. It resolves root path aliases and loads `src/app/theme.css` inside `.storybook/preview.ts`. `__APP_VERSION__` is defined to match `vite.config.ts`. + +### Decision 2: Global Decorators for i18n and Units +In `.storybook/preview.ts`, we declare global toolbar items: +1. `locale`: choices `en` and `ru`. A decorator calls `i18n.changeLanguage(locale)` before rendering. +2. `unit`: choices `mm` and `in`. A decorator wraps stories in ``. +Stories use the standard dark background `#0e1013` (PrintKit background token). + +### Decision 3: Portable Stories Smoke Testing with Vitest +Rather than relying solely on manual browser inspection, we add `src/stories.test.ts` which uses `@storybook/react` portable stories (`composeStories`) to mount every exported story in a jsdom test. Any syntax break, missing translation key crash, or undefined prop will fail `npm test`. + +## Risks & Mitigations +- **Tailwind v4 in Storybook:** Tailwind v4 uses `@theme` directives directly in CSS. We import `src/app/theme.css` in `.storybook/preview.ts` so all custom color tokens (`--color-surface-1`, `--color-accent`, etc.) are available. diff --git a/openspec/changes/44a-storybook/proposal.md b/openspec/changes/44a-storybook/proposal.md new file mode 100644 index 0000000..bc13d93 --- /dev/null +++ b/openspec/changes/44a-storybook/proposal.md @@ -0,0 +1,30 @@ +# Proposal + +## Why + +PrintKit's UI component library (`src/ui/`) and modular editor controls have grown across 44 changes without an isolated visual catalog. Developers currently verify UI states, dark theme tokens, and bilingual labels (EN/RU) by navigating live modes or checking static HTML artboards. Adding Storybook allows isolated component development, interactive state inspection (disabled, error, stepper, units), and automated rendering verification without running the full WASM/WebGL canvas. + +## What Changes + +- **Storybook 8 Integration:** Configure Storybook (`@storybook/react-vite`) inside `.storybook/` integrated with Vite 6/7, Tailwind CSS v4 (`src/app/theme.css`), and the build-time define `__APP_VERSION__`. +- **Global Decorators:** Provide an i18next language switcher (EN / RU) in the Storybook toolbar, a `UnitProvider` toggle (mm / inch), and dark workspace backgrounds matching PrintKit's theme tokens. +- **UI Component Stories:** Add co-located `*.stories.tsx` stories for all foundational controls in `src/ui/` (`Button`, `Toggle`, `SegmentedControl`, `NumberField`, `LengthField`, `Section`, `ConfirmDialog`, `Banner`, `ContextMenu`). +- **Editor Shell Stories:** Add stories with mocked data for key Editor panels and widgets (`Toolbar`, `SketchToolbar`, `Outliner`, `Properties`, `ViewCube`, `MeasurementsBar`). WebGL Viewport is mocked with placeholder boundaries. +- **Automated Smoke Testing:** Add a Vitest test (`stories.test.ts`) using Storybook portable stories (`composeStories`) to assert that every story renders without throwing or logging console errors. +- **NPM Scripts:** Add `npm run storybook` for local development and `npm run build-storybook` for static export into git-ignored `storybook-static/`. + +## Capabilities + +### New Capabilities +- `component-catalog`: Storybook configuration, global theme/i18n/unit decorators, component story definitions, and smoke test suite for the UI library. + +### Modified Capabilities + +## Impact + +- Affects developer tooling and adds devDependencies (`@storybook/react-vite`, `@storybook/react`, etc.). +- Adds `.storybook/main.ts`, `.storybook/preview.ts`, and `*.stories.tsx` files across `src/ui/` and `src/features/editor/`. +- No breaking changes or runtime bundle impact on the production web application. +- Target version: 1.15.1 (patch: developer tooling and component catalog without modifying production geometry or storage schema). +- Out of scope: Visual regression testing services (Chromatic/Percy), deployment of Storybook to public subdomains. +- Depends on: `44-editor-face-tools`. diff --git a/openspec/changes/44a-storybook/specs/component-catalog/spec.md b/openspec/changes/44a-storybook/specs/component-catalog/spec.md new file mode 100644 index 0000000..03d1695 --- /dev/null +++ b/openspec/changes/44a-storybook/specs/component-catalog/spec.md @@ -0,0 +1,46 @@ +# Spec Delta + +## Purpose +Defines the component catalog infrastructure, decorators, story coverage, and rendering smoke verification for PrintKit UI components. + +## ADDED Requirements + +### Requirement: Component Catalog Environment +The development environment SHALL provide an isolated Storybook workspace running under Vite with Tailwind CSS v4 tokens, allowing interactive inspection of UI controls without loading the 3D geometry engine or WebGL viewport. + +#### Scenario: Launching catalog +- **WHEN** the developer executes `npm run storybook` +- **THEN** the Storybook server starts and loads stories with PrintKit dark theme CSS applied + +#### Scenario: Static catalog build +- **WHEN** the developer executes `npm run build-storybook` +- **THEN** static HTML and assets are generated into `storybook-static/` without TypeScript or bundler errors + +### Requirement: Catalog Decorators +Storybook SHALL provide global toolbar controls to toggle the interface language between English and Russian, switch display units between millimetres and inches, and apply PrintKit dark theme backgrounds. + +#### Scenario: Switching language +- **WHEN** the user switches the language toolbar item between EN and RU +- **THEN** all displayed story labels and tooltips update to the selected language using i18next + +#### Scenario: Switching display units +- **WHEN** the user switches the unit toolbar item between mm and in +- **THEN** length fields dynamically recalculate and display values in the active unit while preserving stored millimeters + +### Requirement: Foundation UI Stories +The component catalog SHALL provide stories for all reusable controls in `src/ui/` covering default, focused, disabled, error, and interactive states. + +#### Scenario: LengthField story +- **WHEN** inspecting the `LengthField` story +- **THEN** stepper buttons (+/−), keyboard increment, and unit label are displayed and fully interactive + +#### Scenario: Section story +- **WHEN** inspecting the `Section` story +- **THEN** collapsed state, modified orange summary highlight, and reset actions are demonstrated + +### Requirement: Automated Story Smoke Verification +The test suite SHALL include an automated smoke test asserting that every declared component story mounts successfully in jsdom without runtime exceptions. + +#### Scenario: Story test execution +- **WHEN** `npm test` runs +- **THEN** all stories are evaluated through portable stories and pass with zero unhandled errors diff --git a/openspec/changes/44a-storybook/tasks.md b/openspec/changes/44a-storybook/tasks.md new file mode 100644 index 0000000..f5fbd88 --- /dev/null +++ b/openspec/changes/44a-storybook/tasks.md @@ -0,0 +1,33 @@ +# Tasks + +## 1. Setup and Tooling + +- [ ] 1.1 Install Storybook dependencies (`@storybook/react-vite`, `@storybook/react`, etc.) and configure `.storybook/main.ts` with Vite config resolution and `__APP_VERSION__` definition. Verification: `npx storybook --version`. +- [ ] 1.2 Configure `.storybook/preview.ts` with global CSS (`src/app/theme.css`), i18n decorator with EN/RU toolbar switcher, and `UnitProvider` decorator with mm/in switcher. Verification: Storybook preview loads dark theme tokens. +- [ ] 1.3 Add scripts `storybook` and `build-storybook` to `package.json`, and add `storybook-static/` to `.gitignore`. Verification: `npm run build-storybook` succeeds. + +## 2. Foundation UI Stories (`src/ui/`) + +- [ ] 2.1 Add stories for basic input controls: `Button.stories.tsx`, `Toggle.stories.tsx`, `SegmentedControl.stories.tsx`. Built from `design/artboards/Components.dc.html`. Verification: Stories render in Storybook with all variants. +- [ ] 2.2 Add stories for numeric and measurement controls: `NumberField.stories.tsx`, `LengthField.stories.tsx` (stepper ±, min/max limits, mm and inches). Verification: Interactivity check in Storybook. +- [ ] 2.3 Add stories for layout and container controls: `Section.stories.tsx` (default, modified highlight, reset), `Banner.stories.tsx`, `ConfirmDialog.stories.tsx`. Verification: Visual check in Storybook. + +## 3. Editor Shell Component Stories + +- [ ] 3.1 Add stories for editor navigation: `Toolbar.stories.tsx`, `SketchToolbar.stories.tsx`, `ViewCube.stories.tsx` with mocked callbacks and DoF states. No artboard exists; built from `ui/` components. Verification: Visual check in Storybook. +- [ ] 3.2 Add stories for editor sidebars: `Outliner.stories.tsx` (object hierarchy, lock/visible, health icons) and `Properties.stories.tsx` (transforms, primitive params, mesh health). Verification: Visual check in Storybook. +- [ ] 3.3 Add stories for contextual panels: `ConstraintPanel.stories.tsx`, `FeatureDialog.stories.tsx`, `CutPanel.stories.tsx`. Verification: Visual check in Storybook. + +## 4. Automated Testing and Conventions + +- [ ] 4.1 Create `src/stories.test.ts` using portable stories (`composeStories`) to mount every story in Vitest (jsdom) and assert no console errors or exceptions. Verification: `npm test` passes. +- [ ] 4.2 Document Storybook convention in `AGENTS.md` (all new `src/ui/` components must ship with co-located `*.stories.tsx`). Verification: file check. + +## 5. Version + +- [ ] 5.1 Bump `package.json` to 1.15.1 and add `1.15.1 — 44a-storybook` to `CHANGELOG.md`. Test: `npx vitest run src/site.test.ts`. + +## 6. Verification + +- [ ] 6.1 Run `npm test` and `npm run build` to confirm clean test and TypeScript build. +- [ ] 6.2 Run `npm run build-storybook` to confirm clean static build generation. diff --git a/openspec/changes/44b-editor-viewport-navigation/.openspec.yaml b/openspec/changes/44b-editor-viewport-navigation/.openspec.yaml new file mode 100644 index 0000000..c0ad5ed --- /dev/null +++ b/openspec/changes/44b-editor-viewport-navigation/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-11-08 diff --git a/openspec/changes/44b-editor-viewport-navigation/design.md b/openspec/changes/44b-editor-viewport-navigation/design.md new file mode 100644 index 0000000..bebf673 --- /dev/null +++ b/openspec/changes/44b-editor-viewport-navigation/design.md @@ -0,0 +1,48 @@ +# Design: Viewport Navigation and Adaptive 5×5 Grid + +## Context +CAD applications like FreeCAD and Fusion 360 provide intuitive navigation where zooming continuously reveals finer decimal and 5×5 grid divisions, panning is seamless with standard modifier combinations (`Shift + Drag`), and zoom scaling remains consistent between 3D model space and 2D sketch mode. In PrintKit, fixed shader parameters and unnormalized wheel events created jarring jumps and gesture conflicts. + +## Goals +- Compute hierarchical 5×5 grid intervals based on camera distance and FOV in both perspective and orthographic modes. +- Unify 3D ground grid and sketch plane grid shaders with major line emphasis every 5 minor lines. +- Implement delta-normalized cursor-anchored zoom matching Three.js `OrbitControls.dolly`. +- Route mouse events cleanly to separate camera panning (`Shift + Drag`) from box selection. + +## Non-Goals +- Changing default camera rotation axis from Z-up. +- Fully customizable navigation keybinding profiles. + +## Decisions + +### Decision 1: Pure Grid Level Calculator (`gridLevels.ts`) +We calculate the screen scale `mmPerPx` at the plane target: +`mmPerPx = (2 * distance * Math.tan((fov * Math.PI) / 360)) / viewportHeight` in perspective, or `orthoHeight / viewportHeight` in ortho. +Levels scale by powers of 5 and 10: `..., 0.08, 0.4, 2, 10, 50, 250, 1250, ...`. +Given `mmPerPx`, we determine: +- `minorSpacing`: finest interval with screen spacing $\ge 12\text{ px}$. +- `majorSpacing`: $5 \times \text{minorSpacing}$. +- `subdivisionFade`: a $0..1$ alpha blending factor for the incoming sub-grid. + +### Decision 2: Shared Grid Shader +Instead of creating dozens of line meshes in `buildSketchGrid`, both the ground grid and sketch plane use a custom GLSL shader plane that evaluates coordinates in the plane's local coordinate frame: +`line(coord, minorSpacing)` and `line(coord, majorSpacing)`. +Major lines render with higher opacity and thickness. In sketch mode, X and Y axes retain red and green overlays. + +### Decision 3: OrbitControls-Aligned Zoom in Sketch +In `Viewport.tsx`: +```ts +const deltaY = e.deltaMode === 1 ? e.deltaY * 20 : e.deltaMode === 2 ? e.deltaY * 100 : e.deltaY +const zoomFactor = Math.pow(0.95, -deltaY * 0.002) +``` +This guarantees identical trackpad pinch and mouse wheel sensitivity across 3D and 2D views. + +### Decision 4: Gesture Dispatch Matrix +A pure function `classifyGesture(event, state)` determines action: +- `button === 0 && e.shiftKey && moved > 5`: `pan` +- `button === 0 && !e.shiftKey && moved > 5 && tool === 'select'`: `boxSelect` +- `button === 0 && !e.shiftKey && moved > 5 && isDrawingTool`: `drawDrag` +- `button === 0 && moved <= 5`: `clickSelect` + +## Risks & Mitigations +- **Shader precision at sub-millimetre scales:** High-resolution grids ($0.08\text{ mm}$) can experience floating point moiré at large distances. The shader uses distance-based fadeout (`uFade`) to cull distant sub-grids. diff --git a/openspec/changes/44b-editor-viewport-navigation/proposal.md b/openspec/changes/44b-editor-viewport-navigation/proposal.md new file mode 100644 index 0000000..cb00ebb --- /dev/null +++ b/openspec/changes/44b-editor-viewport-navigation/proposal.md @@ -0,0 +1,31 @@ +# Proposal + +## Why + +Navigation and spatial awareness in the 3D editor and sketch mode suffer from three critical issues: +1. The 3D grid and sketch grid use fixed minor/major spacings (10 mm / 50 mm) without dynamic subdivision; zooming in leaves wide empty gaps instead of revealing sub-millimetre detail. +2. Sketch zoom reacts abruptly to mouse wheel and trackpad gestures because it uses an arbitrary fixed step (`0.87 / 1.15`) rather than the smooth, delta-normalized dolly curve of 3D `OrbitControls`. +3. In sketch mode, dragging with `Shift + Left Click` (the standard FreeCAD/CAD pan shortcut) triggers both view pan and a box-selection rectangle simultaneously. + +## What Changes + +- **Adaptive 5×5 Hierarchical Grid:** Replace fixed grid shaders with a FreeCAD-style hierarchical adaptive grid algorithm. As the camera zooms in or out, sub-grids subdivide recursively in 5×5 steps (e.g. 250 mm → 50 mm → 10 mm → 2 mm → 0.4 mm → 0.08 mm), smoothly fading in and out based on screen pixel density. +- **Unified Sketch Grid with Major 5×5 Lines:** Replace static `LineSegments` in `buildSketchGrid` with the adaptive shader plane. Every 5th line is visually emphasized as a major line, while primary axes (X/Y) retain distinct colored lines. +- **Synchronized Sketch Zoom:** Replace the discrete `onWheel` zoom factor in `Viewport.tsx` with a continuous dolly calculation matching OrbitControls, respecting `deltaMode` (pixel/line/page) and cursor anchoring. +- **Gesture Separation (Shift+Pan vs Box Select):** Distinguish `Shift + Drag` (camera panning) from `Left Drag` (box selection). Shift+Drag pans smoothly without initiating selection rectangles or clearing active drawing states. Additive box selection moves to `Ctrl/Cmd + Drag` or explicit modifier. + +## Capabilities + +### New Capabilities + +### Modified Capabilities +- `model-viewport`: Update the ground grid requirement to specify adaptive hierarchical 5×5 grid subdivision on zoom. +- `editor-sketch`: Update sketch mode navigation to specify adaptive 5×5 grid visualization, synchronized smooth zoom, and Shift+drag camera pan separation. + +## Impact + +- Updates `src/features/viewport/Viewport.tsx`, `src/features/viewport/sketchMesh.ts`, and adds pure tested helper `src/features/viewport/gridLevels.ts` and `src/features/viewport/gesture.ts`. +- Affects both 3D scene view and 2D sketch overlay. +- Target version: 1.16.0 (minor: new adaptive grid visualization and enhanced viewport interaction behaviors). +- Out of scope: User-customizable grid color themes, full navigation style presets (Blender/Revit keys). +- Depends on: `44-editor-face-tools`. diff --git a/openspec/changes/44b-editor-viewport-navigation/specs/editor-sketch/spec.md b/openspec/changes/44b-editor-viewport-navigation/specs/editor-sketch/spec.md new file mode 100644 index 0000000..2794984 --- /dev/null +++ b/openspec/changes/44b-editor-viewport-navigation/specs/editor-sketch/spec.md @@ -0,0 +1,33 @@ +# Spec Delta + +## Purpose +Specifies sketch grid appearance with 5×5 hierarchy, smooth cursor-anchored zoom, and Shift-drag camera panning. + +## MODIFIED Requirements + +### Requirement: Sketch planes and mode +The Editor SHALL create a sketch on the XY, XZ or YZ plane with an offset along the normal, enter a sketch mode that looks at the plane orthogonally with an adaptive 5×5 grid with major line emphasis every 5 divisions, support cursor-anchored smooth zooming matching the 3D viewport, allow camera panning via Shift+drag without creating selection boxes, and leave it with Finish sketch. + +#### Scenario: New sketch +- **WHEN** the user chooses Add → Sketch → XZ plane +- **THEN** a sketch "Sketch 1" is created, the camera looks along the plane normal, the grid is 2D, and the sketch tools replace the scene tools + +#### Scenario: Camera lock +- **WHEN** the user drags with the left button on empty space in sketch mode +- **THEN** the camera does not rotate; wheel and middle-drag still zoom and pan + +#### Scenario: Finish +- **WHEN** the user presses Enter or Finish +- **THEN** the scene mode returns, the sketch stays visible as curves, and one history step "Edit sketch" is kept + +#### Scenario: Adaptive sketch grid +- **WHEN** in sketch mode +- **THEN** the grid displays major lines every 5 minor divisions and adaptively reveals 5×5 subdivisions as the user zooms in + +#### Scenario: Shift drag pans camera +- **WHEN** the user holds Shift and drags with the left mouse button +- **THEN** the camera pans across the sketch plane, and no box-selection rectangle or curve drag is initiated + +#### Scenario: Smooth zoom in sketch +- **WHEN** the user scrolls the mouse wheel or pinches a trackpad in sketch mode +- **THEN** the zoom operates smoothly and continuously around the cursor position without discrete 15% jumps diff --git a/openspec/changes/44b-editor-viewport-navigation/specs/model-viewport/spec.md b/openspec/changes/44b-editor-viewport-navigation/specs/model-viewport/spec.md new file mode 100644 index 0000000..ab6347e --- /dev/null +++ b/openspec/changes/44b-editor-viewport-navigation/specs/model-viewport/spec.md @@ -0,0 +1,29 @@ +# Spec Delta + +## Purpose +Specifies the adaptive 5×5 hierarchical ground grid behavior during camera zooming. + +## MODIFIED Requirements + +### Requirement: Ground grid below the model +The ground grid and the build plate overlay SHALL be hidden while the camera is below the XY plane, and shown again when it comes back above; the change SHALL be smooth, not a sudden jump. The ground grid SHALL dynamically subdivide its cell structure into 5×5 minor divisions as the camera approaches, with major lines every 5 minor subdivisions. + +#### Scenario: Zooming in reveals finer 5x5 divisions +- **WHEN** the user zooms in closer to a surface +- **THEN** nested 5×5 subdivisions fade in smoothly once on-screen cell spacing exceeds 12 pixels, continuing down to sub-millimetre resolution + +#### Scenario: Zooming out collapses divisions +- **WHEN** the user zooms out +- **THEN** minor lines fade out cleanly before becoming dense visual noise, leaving major lines visible + +#### Scenario: Camera goes below +- **WHEN** the camera crosses below the XY plane +- **THEN** the grid and the build plate overlay fade out so the underside is not covered + +#### Scenario: Camera comes back +- **WHEN** the camera returns above the XY plane +- **THEN** the grid and the build plate overlay are shown again + +#### Scenario: Looking along the plane +- **WHEN** the camera is exactly in the XY plane +- **THEN** the grid is hidden or almost invisible, never drawn through the model diff --git a/openspec/changes/44b-editor-viewport-navigation/tasks.md b/openspec/changes/44b-editor-viewport-navigation/tasks.md new file mode 100644 index 0000000..b3cc7b6 --- /dev/null +++ b/openspec/changes/44b-editor-viewport-navigation/tasks.md @@ -0,0 +1,30 @@ +# Tasks + +## 1. Grid Mathematics and Level Calculation + +- [ ] 1.1 Create pure helper `src/features/viewport/gridLevels.ts` calculating `minor`, `major`, and `fade` factors from camera distance, FOV, and screen pixel height with 5×5 stepping. Test: `src/features/viewport/gridLevels.test.ts` (asserts step sequence and fade continuity). +- [ ] 1.2 Implement unified grid shader material supporting dynamic uniform updates (`uMinor`, `uMajor`, `uSubFade`, `uAlpha`, `uFade`). Test: unit test for shader initialization and uniforms. + +## 2. 3D Viewport Ground Grid + +- [ ] 2.1 Update `makeGrid` in `src/features/viewport/Viewport.tsx` to use the dynamic 5×5 level shader and connect render loop uniforms to `gridLevels`. Verification: browser check zooming from 2000 mm down to 1 mm; confirm smooth 5×5 line appearances. +- [ ] 2.2 Verify underside fade and ground plane opacity when orbiting below the XY plane. Verification: browser check with box model viewed from below. + +## 3. Sketch Grid and Navigation + +- [ ] 3.1 Refactor `buildSketchGrid` in `src/features/viewport/sketchMesh.ts` to use the adaptive shader with highlighted major 5×5 lines and preserved colored axes. Test: snapshot / geometry test in `sketchMesh.test.ts`. +- [ ] 3.2 Implement delta-normalized wheel zoom matching OrbitControls in `Viewport.tsx` `onWheel`, keeping cursor anchor intact. Test: unit test verifying zoom factor for mouse wheel and trackpad pinch. +- [ ] 3.3 Separate Shift-drag camera panning from selection gestures in `Viewport.tsx` using `classifyGesture`. Test: `src/features/viewport/gesture.test.ts` (asserts Shift+drag triggers pan and suppresses box selection). + +## 4. Hotkeys and Documentation + +- [ ] 4.1 Update hotkeys popover in `Toolbar.tsx` and i18n keys (`en.json`, `ru.json`) documenting `Shift + Drag` for camera panning and `Ctrl/Cmd + Drag` for additive box selection. Verification: visual check in browser in EN and RU. + +## 5. Version + +- [ ] 5.1 Bump `package.json` to 1.16.0 and add `1.16.0 — 44b-editor-viewport-navigation` to `CHANGELOG.md`. Test: `npx vitest run src/site.test.ts`. + +## 6. Verification + +- [ ] 6.1 Run `npm test` and `npm run build` to ensure all tests pass. +- [ ] 6.2 Browser verification in EN and RU: test zoom smoothness, adaptive 5×5 grid appearance, and Shift+drag panning in both 3D scene and sketch mode. diff --git a/openspec/changes/44c-editor-sketch-input-face/.openspec.yaml b/openspec/changes/44c-editor-sketch-input-face/.openspec.yaml new file mode 100644 index 0000000..c0ad5ed --- /dev/null +++ b/openspec/changes/44c-editor-sketch-input-face/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-11-08 diff --git a/openspec/changes/44c-editor-sketch-input-face/design.md b/openspec/changes/44c-editor-sketch-input-face/design.md new file mode 100644 index 0000000..d7d80cb --- /dev/null +++ b/openspec/changes/44c-editor-sketch-input-face/design.md @@ -0,0 +1,44 @@ +# Design: Universal Sketch HUD and Sequential Face-Modeling + +## Context +Parametric CAD modeling relies on drawing with exact numerical inputs and repeatedly layering features: creating a base solid, picking one of its faces, drawing a sketch, and immediately adding or subtracting material. Currently in PrintKit, only lines and rectangles expose floating HUD inputs, and sketching on faces requires awkward selection mode switching. + +## Goals +- Provide floating HUD input for all sketch drawing tools (Circle, Arc, Point, Polygon). +- Enable direct face selection for "New Sketch" directly from Object mode. +- Link sketches to their host body (`hostObjectId`) and auto-configure Extrude operations (Join/Cut). + +## Decisions + +### Decision 1: Declarative Tool HUD Schema +Instead of hardcoding `isRectTool` in `SketchOverlay.tsx`, we define a pure tool descriptor: +```ts +interface ToolHudSchema { + stages: { + fields: { name: string; label: string; unit?: 'mm' | 'deg'; defaultFromCursor?: boolean }[] + }[] +} +``` +For `circle`: +- Stage 0: `[{ name: 'x', label: 'X' }, { name: 'y', label: 'Y' }]` +- Stage 1: `[{ name: 'size', label: 'R' | 'Ø', toggleKey: 'D' }]` +Submitting Stage 0 moves state to Stage 1. Submitting Stage 1 adds the circle with a driving diameter constraint. + +### Decision 2: Direct Face Raycast in Object Mode +When the user clicks "New Sketch" in the toolbar: +1. The viewport enters a temporary plane-picker state. +2. Raycasting hits either the default planes (XY, XZ, YZ) or any planar face of visible objects. +3. Hovering highlights the candidate face with an accent wireframe border. +4. Clicking resolves `FacePlaneDefinition` with origin and orientation, sets `sketch.hostObjectId = targetObject.id`, and opens sketch mode immediately. + +### Decision 3: Sequential Modeling Transition (Extrude Quick-Action) +When `Finish Sketch` is pressed: +- If the sketch has at least one closed profile: + - The sketch status bar / toast displays `[ Extrude ]` and `[ Revolve ]` quick-action buttons. + - Clicking `Extrude` opens `FeatureDialog` with `sketchId` pre-filled. + - If `sketch.hostObjectId` exists: + - `targetObjectId` defaults to `sketch.hostObjectId`. + - `op` defaults to `join` for positive extrusion distances along the face normal, and `cut` for negative distances. + +## Risks & Mitigations +- **Face normal direction vs extrusion direction:** The face frame normal vector points outward. Extruding with distance $> 0$ adds material (`Join`), while distance $< 0$ enters the body (`Cut`). The UI shows an interactive direction flip toggle. diff --git a/openspec/changes/44c-editor-sketch-input-face/proposal.md b/openspec/changes/44c-editor-sketch-input-face/proposal.md new file mode 100644 index 0000000..0843d39 --- /dev/null +++ b/openspec/changes/44c-editor-sketch-input-face/proposal.md @@ -0,0 +1,35 @@ +# Proposal + +## Why + +Two core CAD modeling limitations currently impede productive sketching: +1. Drawing circles, points, arcs, and regular polygons lacks typed numeric HUD inputs. Users must manually approximate dimensions with the cursor and later add explicit constraints, unlike rectangles and lines which support direct coordinate and dimension typing. +2. Sequential solid modeling ("sketch ➔ extrude ➔ sketch on face ➔ extrude...") is disjointed. Starting a sketch on a face requires switching to Face Selection Mode and hunting for a button in `FaceToolsPanel`. Once drawn, the sketch is not tied to the host body, and finishing the sketch does not prompt an extrusion or auto-select the host body for Join/Cut operations. + +## What Changes + +- **Universal HUD Numeric Input:** Generalize `SketchOverlay.tsx` HUD inputs to all shape tools: + - `circle`: Center `X`, `Y` in Stage 0; Radius `R` or Diameter `Ø` in Stage 1 (toggled with `D` key). + - `point`: Coordinates `X`, `Y`. + - `arc`: Center `X`, `Y` → Radius `R` → Angles `A1`, `A2`. + - `polygon`: Center `X`, `Y` → Circumradius `R` → Side count `N`. + - Pressing `Tab` switches input fields, and `Enter` commits values with automated driving constraints. +- **First-Class Sketch on Face in Object Mode:** In Object Mode, clicking "New Sketch" allows directly picking any planar face under the cursor (highlighted on hover). +- **Host Body Association:** A face sketch records its host object id (`hostObjectId`). Moving or modifying the host object preserves sketch alignment. +- **Seamless Sequential Modeling Flow:** Finishing a closed sketch immediately surfaces a contextual "Extrude" action. When extruding from a face sketch, the operation automatically targets the host body and defaults to `Join` (when extruding outward) or `Cut` (when extruding inward into the body). + +## Capabilities + +### New Capabilities + +### Modified Capabilities +- `editor-sketch`: Expand drawing tools to support universal typed HUD values for Circle, Point, Arc, and Polygon, and enable direct face selection for new sketches. +- `editor-sketch-features`: Update Extrude to auto-target host bodies with directional Join/Cut defaults upon finishing a face-based sketch. + +## Impact + +- Affects `src/features/viewport/SketchOverlay.tsx`, `src/features/editor/sketch/toolStateMachine.ts`, `src/features/editor/sketch/FeatureDialog.tsx`, `src/features/editor/EditorMode.tsx`, and `src/editor/sketch/model.ts`. +- Preserves backwards compatibility for existing sketches and scene documents. +- Target version: 1.17.0 (minor: new interactive HUD input capabilities and sequential face-sketch modeling workflow). +- Out of scope: Sketching on non-planar (curved) surfaces. +- Depends on: `44b-editor-viewport-navigation`. diff --git a/openspec/changes/44c-editor-sketch-input-face/specs/editor-sketch-features/spec.md b/openspec/changes/44c-editor-sketch-input-face/specs/editor-sketch-features/spec.md new file mode 100644 index 0000000..7d0f520 --- /dev/null +++ b/openspec/changes/44c-editor-sketch-input-face/specs/editor-sketch-features/spec.md @@ -0,0 +1,37 @@ +# Spec Delta + +## Purpose +Specifies automated host-body targeting and directional Join/Cut operations when extruding from face-attached sketches. + +## MODIFIED Requirements + +### Requirement: Extrude +The Editor SHALL extrude selected profiles of a sketch by a distance on one side, symmetrically, or by two distances, with the operation New body, Join, Cut or Intersect, showing a live preview while the dialog is open. When extruding from a sketch attached to a face of a host body, the Extrude tool SHALL automatically preselect that host body and default to Join when extruding outward or Cut when extruding inward. + +#### Scenario: New body +- **WHEN** the user extrudes a 40 × 20 rectangle by 10 mm +- **THEN** a body of 40 × 20 × 10 mm with volume 8000 mm³ is created on the sketch plane, and the sketch is hidden + +#### Scenario: Symmetric +- **WHEN** the side is symmetric with distance 10 +- **THEN** the body extends 5 mm to each side of the plane + +#### Scenario: Cut +- **WHEN** the user extrudes a circle with the operation Cut through a body +- **THEN** a hole is made in that body and no new body is created + +#### Scenario: Pick regions +- **WHEN** a sketch has two separate profiles and the user clicks only one in the view +- **THEN** only that profile is extruded + +#### Scenario: Zero distance +- **WHEN** the distance is zero or negative +- **THEN** the field shows the limit and the preview is not updated + +#### Scenario: Face sketch auto-join +- **WHEN** finishing a sketch on the top face of a 20 mm cube and applying an outward 10 mm extrude +- **THEN** Extrude preselects the cube as target with operation Join, creating a combined 30 mm tall solid + +#### Scenario: Face sketch auto-cut +- **WHEN** finishing a sketch on the face of a body and extruding inward with a negative distance into the material +- **THEN** Extrude preselects the body as target with operation Cut diff --git a/openspec/changes/44c-editor-sketch-input-face/specs/editor-sketch/spec.md b/openspec/changes/44c-editor-sketch-input-face/specs/editor-sketch/spec.md new file mode 100644 index 0000000..6b80705 --- /dev/null +++ b/openspec/changes/44c-editor-sketch-input-face/specs/editor-sketch/spec.md @@ -0,0 +1,29 @@ +# Spec Delta + +## Purpose +Specifies universal typed HUD input for all sketch tools and direct face selection when creating sketches. + +## MODIFIED Requirements + +### Requirement: Drawing tools +The sketch mode SHALL provide Line (polyline), Rectangle (two corners or centre, with an optional corner radius), Circle (centre and radius/diameter), Arc (three points, or centre-start-end), Slot and regular Polygon, each accepting typed values for the main dimensions and coordinates while drawing via a floating HUD. + +#### Scenario: Rounded rectangle +- **WHEN** the user draws a rectangle with corner radius 5 mm +- **THEN** four lines and four tangent arcs are created, the radii are tied by an equal constraint, and one radius dimension of 5 mm drives all four + +#### Scenario: Typed values +- **WHEN** the user starts a circle and types 12 and Enter +- **THEN** the circle has radius 12 mm and a radius dimension + +#### Scenario: Slot +- **WHEN** the user draws a slot of length 30 and width 8 +- **THEN** two lines and two arcs are created, tangent to each other, with the width as a dimension + +#### Scenario: Circle typed values +- **WHEN** drawing a circle and the user types X=10, Tab, Y=20, Enter, then types diameter 15 and Enter +- **THEN** a circle centered at (10, 20) with diameter 15 mm is created with driving constraints + +#### Scenario: Direct face selection +- **WHEN** in Object mode the user triggers New Sketch and clicks a highlighted planar face of an object +- **THEN** a sketch is created aligned with that face and linked to the host object without manually switching to Face Selection mode diff --git a/openspec/changes/44c-editor-sketch-input-face/tasks.md b/openspec/changes/44c-editor-sketch-input-face/tasks.md new file mode 100644 index 0000000..dfd23f8 --- /dev/null +++ b/openspec/changes/44c-editor-sketch-input-face/tasks.md @@ -0,0 +1,28 @@ +# Tasks + +## 1. Universal Tool HUD Input System + +- [ ] 1.1 Implement declarative HUD descriptors for circle, arc, point, and polygon in `src/features/viewport/sketchHudSchema.ts`. Test: unit test validating stage transitions and field schemas. +- [ ] 1.2 Refactor `SketchOverlay.tsx` to render floating HUD inputs according to the active tool schema with Tab cycling, Enter commit, and Esc cancel. Test: component test in `SketchOverlay.test.tsx`. +- [ ] 1.3 Connect HUD commitments to `toolStateMachine.ts` so submitted values create points, circles, and driving dimension constraints. Test: unit test in `toolStateMachine.test.ts`. + +## 2. Direct Face Selection for New Sketch + +- [ ] 2.1 Add plane/face picker state in `EditorMode.tsx` when clicking "New Sketch" without requiring Face selection mode. Test: interaction test in `EditorMode.test.tsx`. +- [ ] 2.2 Highlight planar face under cursor in the viewport during plane picking. Verification: visual check in browser on a 3D box. +- [ ] 2.3 Store `hostObjectId` and `faceId` in `Sketch` definition and re-resolve frame when the host body is updated. Test: unit test in `sketch/plane.test.ts`. + +## 3. Sequential Modeling Workflow (Sketch ➔ Extrude) + +- [ ] 3.1 Display contextual `Extrude` action upon finishing a sketch with closed profiles. Verification: visual check in browser. +- [ ] 3.2 Pre-populate `FeatureDialog` with `hostObjectId` and directional `Join` / `Cut` default operation based on extrude sign. Test: component test in `FeatureDialog.test.tsx`. +- [ ] 3.3 End-to-end test of sequential modeling: create box ➔ sketch circle on top face with typed center and diameter ➔ extrude join 10 mm ➔ sketch circle on top of new cylinder ➔ extrude cut 5 mm. Verify closed manifold and volume. Test: `src/features/editor/sequentialModeling.test.ts`. + +## 4. Version + +- [ ] 4.1 Bump `package.json` to 1.17.0 and add `1.17.0 — 44c-editor-sketch-input-face` to `CHANGELOG.md`. Test: `npx vitest run src/site.test.ts`. + +## 5. Verification + +- [ ] 5.1 Run `npm test` and `npm run build` to ensure clean build. +- [ ] 5.2 Browser verification in EN and RU: draw circle with typed coordinates and diameter, create sketch directly on a face, and execute join/cut extrusions. diff --git a/openspec/changes/44d-editor-layout-workbenches/.openspec.yaml b/openspec/changes/44d-editor-layout-workbenches/.openspec.yaml new file mode 100644 index 0000000..c0ad5ed --- /dev/null +++ b/openspec/changes/44d-editor-layout-workbenches/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-11-08 diff --git a/openspec/changes/44d-editor-layout-workbenches/design.md b/openspec/changes/44d-editor-layout-workbenches/design.md new file mode 100644 index 0000000..17351b7 --- /dev/null +++ b/openspec/changes/44d-editor-layout-workbenches/design.md @@ -0,0 +1,37 @@ +# Design: Unified Editor Header and Workbench Workspaces + +## Context +As PrintKit's 3D editor features multiplied, the UI accumulated stacked rows and mismatched sidebars. In standard 1080p and 1440p displays, vertical space is critical for 3D modeling and 2D sketching. Consolidating the top row and equalizing the sidebars with drag-resizing provides a balanced professional CAD workspace. + +## Goals +- Merge the app Header and Editor Toolbar into one 42 px row. +- Introduce explicit `Model` and `Sketch` workbench views. +- Standardize left and right sidebar widths to 280 px with draggable resize handles ($220..460\text{ px}$). +- Eliminate right-panel horizontal scroll and clipped Russian text. + +## Decisions + +### Decision 1: Consolidated Header Architecture +When mounted at `/editor`, the top row renders: +- **Left:** Logo `PrintKit`, document name, Undo / Redo buttons. +- **Center:** Workbench command strip: + - In `Model`: Create (primitives, import, sketch), Transform, Features (Extrude, Revolve, Boolean, Pattern, Push/Pull, EdgeBreak), and Tools (Measure, Split, Repair). + - In `Sketch`: Active sketch badge with plane name, Draw tools, Constraints, Construction toggle, DoF pill, and prominent Finish/Cancel buttons. +- **Right:** Viewport actions (Fit, Ortho/Persp), Export button, Language, and Units. + +### Decision 2: Pure Resize Management (`useSidebarResize.ts`) +We create a pure pointer hook managing width dragging with mouse capture: +- Clamped between $220\text{ px}$ and $460\text{ px}$. +- Double-click on the splitter resets width to $280\text{ px}$. +- Widths are stored in `localStorage` under `editor.ui` as `leftWidth` and `rightWidth`. + +### Decision 3: Right Panel Context Router +The right sidebar displays a single active sub-view with a consistent title and back navigation: +- `Properties` (default when body selected) +- `ConstraintPanel` (active during sketch) +- `FeatureDialog` (active when creating extrude/revolve) +- `CutPanel` / `FaceToolsPanel` +This prevents multiple nested panels from competing for vertical space. + +## Risks & Mitigations +- **Responsive width overflow:** On displays smaller than 1200 px, toolbar items in the center could overflow. We implement an overflow dropdown menu (`...`) for secondary tools. diff --git a/openspec/changes/44d-editor-layout-workbenches/proposal.md b/openspec/changes/44d-editor-layout-workbenches/proposal.md new file mode 100644 index 0000000..f87ce45 --- /dev/null +++ b/openspec/changes/44d-editor-layout-workbenches/proposal.md @@ -0,0 +1,34 @@ +# Proposal + +## Why + +The current editor layout wastes significant vertical screen space and suffers from visual fragmentation: +1. Two stacked full-width horizontal bars (the global app `Header` at 48–56 px and the editor `Toolbar` at 36–40 px) squeeze the 3D viewport. +2. The left sidebar (Outliner) is fixed at 240 px, while the right sidebar is fixed at 300 px; they cannot be resized, causing clipped labels in Russian localization and horizontal scrolling in nested panels. +3. Object tools and sketch tools are mixed without clear context boundaries; in sketch mode, 3D operations remain cluttering the sidebars and properties. + +## What Changes + +- **Unified Single-Row Editor Header:** Integrate the compact app header with the editor command bar into a single streamlined top bar (height 42 px) when inside `/editor`. Global links (Logo, Undo/Redo, Export, Unit, Language) share one row with the workbench command set. +- **Explicit Workbenches (Model vs Sketch):** + - **Model Workbench:** Active when viewing 3D geometry. Exposes object creation (primitives, import, new sketch), transforms (select/move/rotate/scale), solid operations (extrude, revolve, boolean, pattern, push/pull, edge break), and inspection tools. + - **Sketch Workbench:** Active when editing a 2D sketch. Top command row switches completely to drawing tools (Line, Rect, Circle, Arc, Polygon, Slot), constraints, construction toggle, DoF indicator, and a prominent "Finish / Cancel" cluster. Object manipulation tools are hidden. +- **Symmetric Resizable Sidebars:** + - Both left (Outliner) and right (Properties / Context Tool) sidebars default to **280 px**. + - Interactive drag-resizer handles allow resizing between 220 px and 460 px, persisted in `editor.ui`. Double-clicking resets to 280 px. +- **Unified Contextual Container:** The right panel always renders under a single titled container with breadcrumbs (e.g. `Properties > Extrude` or `Properties > Mesh Health`), eliminating cramped nested panels. + +## Capabilities + +### New Capabilities + +### Modified Capabilities +- `editor-workspace`: Update the editor shell requirement to specify a unified single-row header, Model/Sketch workbench isolation, and symmetric resizable sidebars. + +## Impact + +- Affects `src/app/Header.tsx`, `src/features/editor/EditorMode.tsx`, `src/features/editor/Toolbar.tsx`, `src/features/editor/sketch/SketchToolbar.tsx`, and `src/features/editor/editorUiStore.ts`. +- Updates layout styling without breaking stored scene documents. +- Target version: 1.18.0 (minor: layout overhaul with resizable panels and workbench modes). +- Out of scope: User-customizable floating tool palettes or dockable windows. +- Depends on: `44a-storybook`, `44c-editor-sketch-input-face`. diff --git a/openspec/changes/44d-editor-layout-workbenches/specs/editor-workspace/spec.md b/openspec/changes/44d-editor-layout-workbenches/specs/editor-workspace/spec.md new file mode 100644 index 0000000..5865ee1 --- /dev/null +++ b/openspec/changes/44d-editor-layout-workbenches/specs/editor-workspace/spec.md @@ -0,0 +1,29 @@ +# Spec Delta + +## Purpose +Specifies the unified single-row top bar, workbench mode isolation, and symmetric resizable sidebars. + +## MODIFIED Requirements + +### Requirement: Editor shell +The Editor SHALL show an outliner, a 3D view, a properties panel, and a unified command header. The header SHALL integrate site navigation with workbench-specific tools (Model vs Sketch) into a single row. The left and right sidebars SHALL have equal default widths of 280 px and support interactive drag-resizing between 220 px and 460 px with persistent storage. Below 768 px the outliner and properties SHALL be drawers. + +#### Scenario: Desktop +- **WHEN** the window is at least 768 px wide +- **THEN** outliner, view and properties are visible side by side and each side panel can be collapsed + +#### Scenario: Narrow window +- **WHEN** the window is narrower than 768 px +- **THEN** the view fills the screen and the outliner and properties open as bottom drawers from the tool bar + +#### Scenario: Unified header row +- **WHEN** the editor is displayed on desktop +- **THEN** the workspace renders a single consolidated top bar combining project logo, undo/redo, workbench tools, export, and language/unit switches without a secondary stacked toolbar + +#### Scenario: Symmetric resizable sidebars +- **WHEN** the user drags a sidebar border handle +- **THEN** the sidebar width adjusts smoothly between 220 px and 460 px, and double-clicking the handle resets width to 280 px + +#### Scenario: Workbench isolation +- **WHEN** entering sketch mode +- **THEN** the header switches to sketch drawing and constraint tools, the right panel switches to sketch constraints, and 3D object manipulation tools are hidden diff --git a/openspec/changes/44d-editor-layout-workbenches/tasks.md b/openspec/changes/44d-editor-layout-workbenches/tasks.md new file mode 100644 index 0000000..507a69a --- /dev/null +++ b/openspec/changes/44d-editor-layout-workbenches/tasks.md @@ -0,0 +1,26 @@ +# Tasks + +## 1. Unified Single-Row Header + +- [ ] 1.1 Implement consolidated header in `src/features/editor/EditorHeader.tsx` uniting global navigation, workbench tool strips, and right-aligned viewport/export actions into a 42 px row. No artboard exists; built from `ui/` components. Test: component test in `EditorHeader.test.tsx`. +- [ ] 1.2 Update `src/app/AppShell.tsx` and `src/features/editor/EditorMode.tsx` to mount the consolidated header and eliminate the secondary stacked toolbar. Verification: visual check in browser in EN and RU. + +## 2. Workbench State and Tool Strips + +- [ ] 2.1 Refactor `Toolbar.tsx` into Model Workbench tool groups (Create, Transform, Feature, Tools) with overflow dropdown handling. Test: interaction test in `Toolbar.test.tsx`. +- [ ] 2.2 Refactor `SketchToolbar.tsx` into Sketch Workbench tool strip with sketch badge, drawing tools, constraints, DoF counter, and Finish/Cancel buttons. Test: component test in `SketchToolbar.test.tsx`. + +## 3. Symmetric Resizable Sidebars + +- [ ] 3.1 Implement draggable splitter handle with bounds 220–460 px and double-click reset to 280 px in `src/features/editor/SidebarSplitter.tsx`. Test: unit test in `SidebarSplitter.test.tsx`. +- [ ] 3.2 Update `EditorMode.tsx` left Outliner and right Properties panels to use 280 px default width with persisted sizes in `editor.ui`. Verification: drag sidebars, refresh page, confirm widths persist. +- [ ] 3.3 Audit and fix all right-sidebar panels (`Properties.tsx`, `FeatureDialog.tsx`, `ConstraintPanel.tsx`) for 280 px width compatibility in Russian and English without horizontal overflow. Verification: visual check in browser. + +## 4. Version + +- [ ] 4.1 Bump `package.json` to 1.18.0 and add `1.18.0 — 44d-editor-layout-workbenches` to `CHANGELOG.md`. Test: `npx vitest run src/site.test.ts`. + +## 5. Verification + +- [ ] 5.1 Run `npm test` and `npm run build` to ensure clean build. +- [ ] 5.2 Browser verification in EN and RU: test layout at 1280×800 and 1920×1080; verify workbench switching between Model and Sketch; test sidebar dragging and collapse toggles. diff --git a/openspec/changes/44e-editor-context-menu/.openspec.yaml b/openspec/changes/44e-editor-context-menu/.openspec.yaml new file mode 100644 index 0000000..c0ad5ed --- /dev/null +++ b/openspec/changes/44e-editor-context-menu/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-11-08 diff --git a/openspec/changes/44e-editor-context-menu/design.md b/openspec/changes/44e-editor-context-menu/design.md new file mode 100644 index 0000000..ff64aa2 --- /dev/null +++ b/openspec/changes/44e-editor-context-menu/design.md @@ -0,0 +1,41 @@ +# Design: Universal Viewport Context Menu + +## Context +Currently in PrintKit, only Outliner rows implement `onContextMenu`. Users interacting directly with objects, faces, or sketch profiles on the 3D canvas must divert focus to sidebars or toolbar buttons. Providing direct right-click contextual actions accelerates workflow and follows standard CAD usability conventions. + +## Goals +- Create a shared `src/ui/ContextMenu.tsx` primitive. +- Unify Outliner actions and Viewport actions through a pure `contextActions(target, state)` action provider. +- Implement reliable right-click disambiguation against OrbitControls camera dragging. +- Support full keyboard accessibility (`ArrowUp`, `ArrowDown`, `Enter`, `Escape`). + +## Decisions + +### Decision 1: Shared Action Tree Provider (`src/features/editor/contextActions.ts`) +We decouple menu rendering from event origin: +```ts +export interface MenuItem { + id: string + label: string + icon?: ComponentType + hotkey?: string + disabled?: boolean + danger?: boolean + separator?: boolean + action?: () => void + children?: MenuItem[] +} +``` +`buildObjectActions(objectId, doc, dispatch)` builds identical items whether triggered from an Outliner row or a 3D body click. + +### Decision 2: Pointer Release Disambiguation in Viewport +In `Viewport.tsx`: +- On `pointerdown` with `e.button === 2`: record `downPos = { x: e.clientX, y: e.clientY }`. +- On `pointermove`: if $\text{hypot}(\Delta x, \Delta y) > 4$, mark `isNavigating = true`. +- On `pointerup` with `e.button === 2`: if `!isNavigating`, prevent default browser menu and fire `onContextMenu({ x, y, hit })`. + +### Decision 3: Touch Support +On touch devices, a 500 ms long-press gesture on any entity dispatches the same context menu event at the touch coordinates. + +## Risks & Mitigations +- **Context menu off-screen overflow:** The menu measures its rendered rect via `getBoundingClientRect` and flips orientation to stay within viewport bounds. diff --git a/openspec/changes/44e-editor-context-menu/proposal.md b/openspec/changes/44e-editor-context-menu/proposal.md new file mode 100644 index 0000000..670b553 --- /dev/null +++ b/openspec/changes/44e-editor-context-menu/proposal.md @@ -0,0 +1,34 @@ +# Proposal + +## Why + +Contextual actions in PrintKit are severely constrained: right-clicking only works on rows inside the left Outliner tree. In the 3D viewport and the 2D sketch canvas, right-clicking is either captured exclusively by camera navigation or ignored completely. Users cannot right-click directly on a solid body, face, edge, empty space, or sketch entity to trigger natural CAD operations. + +## What Changes + +- **Universal Context Menu Component (`ui/ContextMenu`):** A portal-rendered, keyboard-navigable context menu component with submenus, separators, keyboard shortcut badges, and boundary-aware positioning. +- **3D Viewport Right-Click Menu:** + - **On 3D Object:** Select, Rename, Hide/Show, Isolate, Duplicate, Delete, Fit, Operations submenu (Boolean, Mirror, Pattern), Repair (for meshes), Export Selected. + - **On Empty 3D Space:** Add Primitive submenu, Import files, New Sketch (plane selector), Paste, Show All, Fit All. + - **On Face (Face mode or hover):** New Sketch on this face, Push/Pull, Fillet face edges, Lay on Bed, Measure. + - **On Edge (Edge mode or hover):** Fillet, Chamfer, Select chain. +- **2D Sketch Right-Click Menu:** + - **On Sketch Entity:** Applicable geometric constraints (Coincident, Horizontal, Vertical, Tangent, Dimension), Construction toggle, Delete, Trim. + - **On Empty Sketch Canvas:** Quick-switch draw tools, Normal to Sketch view, Finish Sketch, Cancel Sketch. +- **Gesture Disambiguation:** Right-click context menus open only on pointer release (`pointerup`) when total pointer movement during click is $\le 4\text{ px}$, preventing unwanted menu triggers during right-mouse camera orbits. + +## Capabilities + +### New Capabilities +- `editor-context-menu`: Universal context menu system for 3D objects, faces, edges, empty space, and 2D sketch entities. + +### Modified Capabilities +- `editor-workspace`: Update editor shell requirements to specify viewport context menu availability across objects and canvas space. + +## Impact + +- Affects `src/ui/ContextMenu.tsx`, `src/features/viewport/Viewport.tsx`, `src/features/editor/Outliner.tsx`, `src/features/editor/EditorMode.tsx`, and `src/features/viewport/SketchOverlay.tsx`. +- Standardizes Outliner context actions with 3D viewport actions via a shared action builder. +- Target version: 1.19.0 (minor: comprehensive contextual menu system across all editor viewports). +- Out of scope: User-customizable context menu editor. +- Depends on: `44c-editor-sketch-input-face`, `44d-editor-layout-workbenches`. diff --git a/openspec/changes/44e-editor-context-menu/specs/editor-context-menu/spec.md b/openspec/changes/44e-editor-context-menu/specs/editor-context-menu/spec.md new file mode 100644 index 0000000..9826b34 --- /dev/null +++ b/openspec/changes/44e-editor-context-menu/specs/editor-context-menu/spec.md @@ -0,0 +1,43 @@ +# Spec Delta + +## Purpose +Defines the context menu behavior, target resolution, and menu actions across 3D objects, faces, edges, canvas space, and 2D sketches. + +## ADDED Requirements + +### Requirement: 3D Scene Context Menu +The 3D Viewport SHALL open a context menu on right-click without drag on 3D objects, faces, edges, and empty space, presenting relevant actions according to the clicked target. + +#### Scenario: Object context menu +- **WHEN** the user right-clicks on an unselected 3D object +- **THEN** the object is selected and the menu offers Rename, Hide, Duplicate, Delete, Fit, Operations, and Repair + +#### Scenario: Empty space context menu +- **WHEN** the user right-clicks on empty background in the 3D viewport +- **THEN** the menu offers Add Primitive, Import, New Sketch on plane, Show All, and Fit All + +#### Scenario: Face context menu +- **WHEN** the user right-clicks on a planar face +- **THEN** the menu offers New Sketch on Face, Push/Pull, Lay on Bed, and Measure + +#### Scenario: Edge context menu +- **WHEN** the user right-clicks on an edge +- **THEN** the menu offers Fillet, Chamfer, and Select Edge Chain + +### Requirement: Sketch Canvas Context Menu +The 2D sketch canvas SHALL open a context menu on right-click without drag, presenting valid geometric constraints and operations for clicked entities or canvas actions on empty space. + +#### Scenario: Entity context menu +- **WHEN** the user right-clicks on a sketch curve or point +- **THEN** the menu offers applicable geometric constraints (Horizontal, Vertical, Tangent, Dimension), Construction toggle, and Delete + +#### Scenario: Empty sketch canvas context menu +- **WHEN** the user right-clicks on empty space in sketch mode +- **THEN** the menu offers drawing tool shortcuts, View Normal to Sketch, Finish Sketch, and Cancel Sketch + +### Requirement: Camera Drag Disambiguation +The viewport SHALL distinguish camera orbit and pan gestures using the right mouse button from context menu invocations. + +#### Scenario: Right button drag +- **WHEN** the user presses the right mouse button and moves the cursor more than 4 pixels before releasing +- **THEN** the camera navigates and no context menu opens diff --git a/openspec/changes/44e-editor-context-menu/specs/editor-workspace/spec.md b/openspec/changes/44e-editor-context-menu/specs/editor-workspace/spec.md new file mode 100644 index 0000000..853770f --- /dev/null +++ b/openspec/changes/44e-editor-context-menu/specs/editor-workspace/spec.md @@ -0,0 +1,33 @@ +# Spec Delta + +## Purpose +Specifies context menu support in the editor viewport shell. + +## MODIFIED Requirements + +### Requirement: Editor shell +The Editor SHALL show an outliner, a 3D view, a properties panel, and a unified command header. The header SHALL integrate site navigation with workbench-specific tools (Model vs Sketch) into a single row. The left and right sidebars SHALL have equal default widths of 280 px and support interactive drag-resizing between 220 px and 460 px with persistent storage. The 3D view and 2D sketch canvas SHALL support right-click context menus. Below 768 px the outliner and properties SHALL be drawers. + +#### Scenario: Desktop +- **WHEN** the window is at least 768 px wide +- **THEN** outliner, view and properties are visible side by side and each side panel can be collapsed + +#### Scenario: Narrow window +- **WHEN** the window is narrower than 768 px +- **THEN** the view fills the screen and the outliner and properties open as bottom drawers from the tool bar + +#### Scenario: Unified header row +- **WHEN** the editor is displayed on desktop +- **THEN** the workspace renders a single consolidated top bar combining project logo, undo/redo, workbench tools, export, and language/unit switches without a secondary stacked toolbar + +#### Scenario: Symmetric resizable sidebars +- **WHEN** the user drags a sidebar border handle +- **THEN** the sidebar width adjusts smoothly between 220 px and 460 px, and double-clicking the handle resets width to 280 px + +#### Scenario: Workbench isolation +- **WHEN** entering sketch mode +- **THEN** the header switches to sketch drawing and constraint tools, the right panel switches to sketch constraints, and 3D object manipulation tools are hidden + +#### Scenario: Viewport context menu +- **WHEN** the user right-clicks on a viewport entity or canvas without dragging +- **THEN** an accessible context menu opens with commands relevant to the selection diff --git a/openspec/changes/44e-editor-context-menu/tasks.md b/openspec/changes/44e-editor-context-menu/tasks.md new file mode 100644 index 0000000..b080b69 --- /dev/null +++ b/openspec/changes/44e-editor-context-menu/tasks.md @@ -0,0 +1,26 @@ +# Tasks + +## 1. ContextMenu UI Component + +- [ ] 1.1 Implement accessible `src/ui/ContextMenu.tsx` with screen boundary clamping, submenus, hotkey badges, and keyboard navigation (Arrows, Enter, Esc). Built from `design/artboards/Components.dc.html`. Test: `ContextMenu.test.tsx` and Storybook story. +- [ ] 1.2 Implement pure action tree builder `src/features/editor/contextActions.ts` for objects, empty space, faces, edges, and sketch entities. Test: unit tests in `contextActions.test.ts`. + +## 2. 3D Viewport Integration + +- [ ] 2.1 Implement right-click pointerup disambiguation in `src/features/viewport/Viewport.tsx` to separate camera orbit from menu opening. Test: unit test in `Viewport.test.tsx`. +- [ ] 2.2 Wire up 3D object and empty-space context menus in `EditorMode.tsx`. Verification: browser check right-clicking objects and background. +- [ ] 2.3 Wire up face and edge context menus (Sketch on face, Push/Pull, Fillet, Chamfer). Verification: browser check on box model in Face/Edge mode. + +## 3. Sketch Overlay and Outliner Integration + +- [ ] 3.1 Refactor `Outliner.tsx` to use `ContextMenu` and `contextActions`. Test: component test in `Outliner.test.tsx`. +- [ ] 3.2 Wire up sketch canvas right-click in `SketchOverlay.tsx` with constraints for entities and canvas actions on background. Test: component test in `SketchOverlay.test.tsx`. + +## 4. Version + +- [ ] 4.1 Bump `package.json` to 1.19.0 and add `1.19.0 — 44e-editor-context-menu` to `CHANGELOG.md`. Test: `npx vitest run src/site.test.ts`. + +## 5. Verification + +- [ ] 5.1 Run `npm test` and `npm run build` to ensure clean build. +- [ ] 5.2 Browser verification in EN and RU: test context menu on 3D body, empty space, face, edge, Outliner row, and sketch entity. diff --git a/openspec/changes/44f-editor-op-preview/.openspec.yaml b/openspec/changes/44f-editor-op-preview/.openspec.yaml new file mode 100644 index 0000000..c0ad5ed --- /dev/null +++ b/openspec/changes/44f-editor-op-preview/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-11-08 diff --git a/openspec/changes/44f-editor-op-preview/design.md b/openspec/changes/44f-editor-op-preview/design.md new file mode 100644 index 0000000..2c1efd3 --- /dev/null +++ b/openspec/changes/44f-editor-op-preview/design.md @@ -0,0 +1,32 @@ +# Design: Operation Preview Pipeline + +## Context +In professional CAD software, parameter changes render instantaneous ghost geometry so users can evaluate topology and collisions. PrintKit's Web Worker architecture evaluates operations via `Manifold` and already uses translucent meshes for Cutout tools. We extend this mechanism to provide instantaneous visual previews for Extrude, Revolve, and Face ops. + +## Goals +- Add an asynchronous `preview` worker lane with debouncing (60 ms) and cancellation. +- Render color-coded preview meshes in `Viewport.tsx`: Blue for additions, Red for subtractions, Purple for intersections. +- Implement a 3D arrow gizmo for distance dragging with snapping. +- Maintain zero mutation of the persistent scene document until "Apply". + +## Decisions + +### Decision 1: Dedicated Worker Preview Lane +In `modelClient.ts`, we add `requestPreview(op, params)`: +- Cancels previous inflight preview requests. +- Uses a 60 ms debounce. +- Evaluates only the candidate operation (or reuses prefix cache for stack operations). +- Returns `MeshData` with `colorKind: 'join' | 'cut' | 'intersect'`. + +### Decision 2: Viewport Ghost Mesh Layer +In `Viewport.tsx`, an independent `previewGroup: THREE.Group` holds: +- The translucent mesh with `MeshPhysicalMaterial`: + - `transparent: true`, `opacity: 0.55`, `depthWrite: false` + - Color bound to theme tokens: Blue (`#3b82f6`), Red (`#ef4444`), Purple (`#a855f7`). +- The 3D drag arrow: a cone + cylinder aligned with the extrusion normal vector. Drag events update the active tool distance state directly. + +### Decision 3: Fast Cancellation on Dismiss +When `FeatureDialog` or `FaceToolsPanel` unmounts or cancels, `onClearPreview()` immediately disposes of geometries in `previewGroup` and cancels pending worker calculations. + +## Risks & Mitigations +- **Heavy mesh compute lag:** On meshes with $>100\text{k}$ triangles, booleans can take $>200\text{ ms}$. If preview calculation exceeds $150\text{ ms}$, we compute and render the extrusion tool shape first (instant prism/cylinder), and compute the full CSG boolean in the background. diff --git a/openspec/changes/44f-editor-op-preview/proposal.md b/openspec/changes/44f-editor-op-preview/proposal.md new file mode 100644 index 0000000..ec14e34 --- /dev/null +++ b/openspec/changes/44f-editor-op-preview/proposal.md @@ -0,0 +1,31 @@ +# Proposal + +## Why + +Modifying solid geometry operations in PrintKit is currently a "blind" process: when configuring Extrude, Revolve, Push/Pull, or Edge Fillet/Chamfer, the 3D scene remains completely static until the user presses "Apply". Users cannot visually gauge whether an extrusion clears a pocket or if a fillet radius looks proportional without repeatedly applying, undoing, and readjusting parameters. + +## What Changes + +- **Interactive Ghost Preview in Viewport:** While configuring an operation in `FeatureDialog`, `FaceToolsPanel`, or `Properties`, a translucent preview body renders in real time in the 3D viewport. +- **Color-Coded Operation Feedback:** + - `Join` / `New Body`: Translucent accent blue (`--color-accent`, opacity ~0.55). + - `Cut`: Translucent danger red (`--color-danger`, opacity ~0.55). + - `Intersect`: Translucent purple (`--color-badge-purple`, opacity ~0.55). +- **Asynchronous Worker Preview Lane:** Dedicated `preview` communication lane in the Web Worker with 60 ms debouncing, cancellation of stale jobs, and prefix-cache reuse, ensuring immediate response without freezing the UI. +- **On-Canvas Distance Drag Handle:** An interactive on-canvas arrow handle aligned with the extrusion or push/pull normal vector, allowing direct dragging in 3D with step snapping while keeping panel inputs synchronized. +- **Clean Document Isolation:** Ghost preview geometry is strictly isolated from the document state, history stack, measurements, and export pipelines; closing or canceling the dialog instantly clears the preview. + +## Capabilities + +### New Capabilities +- `editor-op-preview`: Real-time translucent preview and interactive 3D drag handles for solid modeling operations. + +### Modified Capabilities + +## Impact + +- Affects `src/geometry/model.ts`, `src/geometry/mesh/mesh.worker.ts`, `src/features/viewport/Viewport.tsx`, `src/features/editor/sketch/FeatureDialog.tsx`, and `src/features/editor/face/FaceToolsPanel.tsx`. +- Reuses existing `PrefixCache` and translucent tool rendering shaders. +- Target version: 1.20.0 (minor: interactive real-time visual feedback for 3D operations). +- Out of scope: Previewing multi-operation combinations simultaneously. +- Depends on: `44d-editor-layout-workbenches`. diff --git a/openspec/changes/44f-editor-op-preview/specs/editor-op-preview/spec.md b/openspec/changes/44f-editor-op-preview/specs/editor-op-preview/spec.md new file mode 100644 index 0000000..79d97a7 --- /dev/null +++ b/openspec/changes/44f-editor-op-preview/specs/editor-op-preview/spec.md @@ -0,0 +1,35 @@ +# Spec Delta + +## Purpose +Defines the real-time translucent operation preview and on-canvas interactive manipulation handles for solid modeling operations. + +## ADDED Requirements + +### Requirement: Real-Time Translucent Preview +The Editor SHALL display a translucent preview body of solid modeling operations (Extrude, Revolve, Push/Pull, and Edge Fillet/Chamfer) in the 3D viewport while their parameter dialog is open, updating dynamically as distances and options change. + +#### Scenario: Extrude join preview +- **WHEN** configuring an outward Extrude with operation Join +- **THEN** a translucent accent-colored body representing the extruded volume is rendered extending from the profile + +#### Scenario: Extrude cut preview +- **WHEN** configuring an inward Extrude with operation Cut +- **THEN** a translucent red body representing the volume being subtracted is rendered intersecting the target solid + +#### Scenario: Push/pull preview +- **WHEN** dragging the push/pull distance slider on a planar face +- **THEN** the face's projected displacement is rendered dynamically before committing + +### Requirement: Interactive On-Canvas Drag Handle +Operations with directional distances SHALL display an interactive 3D arrow handle along their normal vector that can be dragged directly in the viewport. + +#### Scenario: Dragging extrusion handle +- **WHEN** the user drags the arrow handle along the extrusion vector +- **THEN** the distance updates continuously with grid snapping, and the numeric field in the dialog synchronizes + +### Requirement: Preview Isolation +Preview bodies SHALL NOT be added to the scene document, SHALL NOT affect bounding box calculations or measurements, and SHALL NOT be included in STL or 3MF exports. + +#### Scenario: Canceling operation +- **WHEN** the user presses Cancel or Escape in an operation dialog +- **THEN** the translucent preview body is instantly removed from the viewport without leaving residual geometry diff --git a/openspec/changes/44f-editor-op-preview/tasks.md b/openspec/changes/44f-editor-op-preview/tasks.md new file mode 100644 index 0000000..2da585c --- /dev/null +++ b/openspec/changes/44f-editor-op-preview/tasks.md @@ -0,0 +1,26 @@ +# Tasks + +## 1. Worker Preview Pipeline + +- [ ] 1.1 Implement preview request lane in `src/geometry/mesh/mesh.worker.ts` with job cancellation and prefix cache reuse. Test: worker test in `modelClient.test.ts`. +- [ ] 1.2 Implement `useOpPreview` hook in `src/features/editor/useOpPreview.ts` with 60 ms debounce, failure handling, and geometry cleanup. Test: unit test in `useOpPreview.test.ts`. + +## 2. 3D Viewport Ghost Rendering and Drag Handle + +- [ ] 2.1 Add `previewMesh` prop and rendering in `src/features/viewport/Viewport.tsx` using translucent color-coded physical materials (Blue Join, Red Cut, Purple Intersect). Test: mock test in `Viewport.test.tsx`. +- [ ] 2.2 Add interactive 3D arrow drag handle for directional distance adjustment with snap intervals. Test: interaction test in `Viewport.test.tsx`. + +## 3. UI Integration across Operations + +- [ ] 3.1 Connect live preview to `FeatureDialog.tsx` for Extrude and Revolve operations. Verification: visual check in browser dragging extrusion height. +- [ ] 3.2 Connect live preview to `FaceToolsPanel.tsx` for Push/Pull and EdgeBreak operations. Verification: visual check in browser pushing/pulling a cube face. +- [ ] 3.3 Verify preview geometry is completely ignored during measurement, bounding box, and STL export. Test: unit test in `editorParts.test.ts`. + +## 4. Version + +- [ ] 4.1 Bump `package.json` to 1.20.0 and add `1.20.0 — 44f-editor-op-preview` to `CHANGELOG.md`. Test: `npx vitest run src/site.test.ts`. + +## 5. Verification + +- [ ] 5.1 Run `npm test` and `npm run build` to ensure clean build. +- [ ] 5.2 Browser verification in EN and RU: test Extrude Join and Cut preview, Push/Pull ghost preview, and drag handle interaction. diff --git a/openspec/changes/44g-editor-split-panel/.openspec.yaml b/openspec/changes/44g-editor-split-panel/.openspec.yaml new file mode 100644 index 0000000..c0ad5ed --- /dev/null +++ b/openspec/changes/44g-editor-split-panel/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-11-08 diff --git a/openspec/changes/44g-editor-split-panel/design.md b/openspec/changes/44g-editor-split-panel/design.md new file mode 100644 index 0000000..43833b8 --- /dev/null +++ b/openspec/changes/44g-editor-split-panel/design.md @@ -0,0 +1,31 @@ +# Design: Non-Modal Split Panel and 3D Viewport Integration + +## Context +Splitting a large model across print beds is an interactive spatial problem. Hiding the 3D scene behind a modal dialog prevents users from judging cut locations relative to model features. Shifting Split to a right sidebar panel aligns it with `CutPanel.tsx` and provides continuous 3D feedback. + +## Goals +- Remove modal `SplitDialog.tsx` in favor of `SplitPanel.tsx` in the right sidebar. +- Display the target object name and dimensions prominently in the panel header. +- Provide real-time 3D cut preview: translucent cut planes, bed footprint, and part color coding. +- Structure connector configuration per cut face with clear orientation labels. + +## Decisions + +### Decision 1: Shared Export Printer Profile +Instead of duplicating bed dimensions, `SplitPanel.tsx` reads `useExportSettings()`: +- Usable width: `bed.width - 2 * bed.margin` +- Usable depth: `bed.depth - 2 * bed.margin` +A "Custom" override allows setting arbitrary dimensions for non-standard beds. + +### Decision 2: 3D Viewport Split Layer +In `Viewport.tsx`, when `splitConfig` is active: +1. Ground bed rectangle is drawn beneath the object origin in dashed accent color. +2. Translucent planes are rendered at positions along X, Y, and Z. +3. Candidate parts are rendered in distinct colors ($A1, B1, \dots$). +4. An exploded view slider moves candidate parts outward along the normal of their cut planes for inspection. + +### Decision 3: Per-Cut Connector Inspector +A list of cuts (e.g. `Cut X1 = 120 mm: Part A1 ↔ Part B1`) lets the user select one cut at a time. The 2D `ConnectorEditor` displays only the selected cut's cross-section with labelled arrows pointing towards each adjoining part. + +## Risks & Mitigations +- **Multiple objects selected:** If multiple objects or no object is selected when clicking Split, the panel prompts: "Select a single object to split". diff --git a/openspec/changes/44g-editor-split-panel/proposal.md b/openspec/changes/44g-editor-split-panel/proposal.md new file mode 100644 index 0000000..099e681 --- /dev/null +++ b/openspec/changes/44g-editor-split-panel/proposal.md @@ -0,0 +1,38 @@ +# Proposal + +## Why + +Splitting large models to fit printer beds currently relies on a detached modal dialog (`SplitDialog.tsx`) that creates several user experience issues: +1. The modal obscures the entire 3D scene, severing visual connection to the model. +2. It is not obvious which object is being split (no target name or dimensions shown in the modal header). +3. The 2D slice preview at the bottom of the dialog only shows a single isolated cross-section without spatial orientation or indication of which cut it represents. +4. Bed sizes are selected from a hardcoded list of presets rather than sharing the user's active 3D printer settings from the export configuration. + +## What Changes + +- **Non-Modal Side Panel (`SplitPanel`):** Replace `SplitDialog.tsx` with a contextual tool panel in the right sidebar, keeping the 3D viewport visible and interactive throughout. +- **Explicit Target Object Presentation:** The panel header prominently displays `Split: ` with object dimensions ($X \times Y \times Z\text{ mm}$) contrasted against usable bed size ($W \times D\text{ mm}$). +- **Interactive 3D Cut Preview:** + - Render translucent cutting planes directly inside the 3D viewport with draggable position handles. + - Render the active printer bed footprint outline directly below the object. + - Live color-code resulting split parts ($A1, B1, \dots$) with warning highlights for oversize parts. + - Interactive exploded view slider to inspect mating faces in 3D. +- **Understandable Connector Placement:** Replace the disconnected 2D canvas with a per-cut selector ("Cut X1 at 120 mm") that clearly shows the two adjoining part labels and allows toggling pegs, pins, magnets, or dovetails. +- **Export Settings Bed Integration:** Default bed dimensions ($W, D, \text{margin}$) are derived directly from the global export printer profile (`data/printers.ts`), while retaining a custom override. + +## Capabilities + +### New Capabilities + +### Modified Capabilities +- `editor-plane-cut`: Update the Split to Bed requirement to specify non-modal panel configuration and real-time 3D viewport cut preview. +- `editor-cut-connectors`: Update placement requirements to support per-cut inspection and selection from the 3D scene. + +## Impact + +- Removes `src/features/editor/cut/SplitDialog.tsx`. +- Adds `src/features/editor/cut/SplitPanel.tsx` and updates `EditorMode.tsx`. +- Connects bed dimensions to `useExportSettings()` from `src/features/export/`. +- Target version: 1.20.1 (patch: user interface rework of an existing capability without data schema changes). +- Out of scope: Non-planar or arbitrary angled split cuts. +- Depends on: `44d-editor-layout-workbenches`, `44f-editor-op-preview`. diff --git a/openspec/changes/44g-editor-split-panel/specs/editor-cut-connectors/spec.md b/openspec/changes/44g-editor-split-panel/specs/editor-cut-connectors/spec.md new file mode 100644 index 0000000..1287136 --- /dev/null +++ b/openspec/changes/44g-editor-split-panel/specs/editor-cut-connectors/spec.md @@ -0,0 +1,25 @@ +# Spec Delta + +## Purpose +Specifies per-cut connector configuration and inspection for multi-axis part splits. + +## MODIFIED Requirements + +### Requirement: Placement +Connectors SHALL be placed automatically over the cut section, evenly and away from the outline, and SHALL be movable, addable and removable in a section preview with explicit cut selection. + +#### Scenario: Two connectors +- **WHEN** count 2 is chosen on a rectangular section +- **THEN** the connectors are spread along the longer side with equal margins + +#### Scenario: Drag +- **WHEN** the user drags a connector in the preview +- **THEN** it moves and the check runs again for the new position + +#### Scenario: Thin section +- **WHEN** the section is too small for any connector +- **THEN** none is placed and the message says why + +#### Scenario: Per-cut section selection +- **WHEN** multiple cuts are defined on an object +- **THEN** the user can select an individual cut by its coordinate to view its specific cross-section and configure connectors for that mating boundary diff --git a/openspec/changes/44g-editor-split-panel/specs/editor-plane-cut/spec.md b/openspec/changes/44g-editor-split-panel/specs/editor-plane-cut/spec.md new file mode 100644 index 0000000..933d43e --- /dev/null +++ b/openspec/changes/44g-editor-split-panel/specs/editor-plane-cut/spec.md @@ -0,0 +1,29 @@ +# Spec Delta + +## Purpose +Specifies the non-modal side panel interface and 3D preview for splitting parts to fit printer beds. + +## MODIFIED Requirements + +### Requirement: Split to bed +The Editor SHALL provide a non-modal tool panel to compute and adjust cuts needed to fit a named object within the printer bed from export settings, display interactive 3D cut planes and bed bounds in the viewport, allow adjusting each cut, and label parts A1, B1… + +#### Scenario: Long part +- **WHEN** a 500 × 100 × 40 mm part is split for a 256 mm bed with a 5 mm margin +- **THEN** three parts are created along X, each not longer than 246 mm + +#### Scenario: Oversize left +- **WHEN** a part still exceeds the bed after the cuts (for example diagonally) +- **THEN** it is marked oversize with the same warning as in the export panel + +#### Scenario: Printer change +- **WHEN** the printer in the export settings is changed +- **THEN** the suggested cuts are recomputed, manual cut positions are kept + +#### Scenario: Target object presentation +- **WHEN** the user opens Split to Bed +- **THEN** the panel header names the target object, displays its bounding box dimensions alongside usable bed dimensions, and highlights the target in 3D + +#### Scenario: Interactive 3D cut preview +- **WHEN** configuring split cuts +- **THEN** the 3D viewport renders the printer bed footprint beneath the part, displays translucent cut planes with position handles, and shows color-coded candidate parts diff --git a/openspec/changes/44g-editor-split-panel/tasks.md b/openspec/changes/44g-editor-split-panel/tasks.md new file mode 100644 index 0000000..60c41c1 --- /dev/null +++ b/openspec/changes/44g-editor-split-panel/tasks.md @@ -0,0 +1,27 @@ +# Tasks + +## 1. Split Panel Implementation + +- [ ] 1.1 Create `src/features/editor/cut/SplitPanel.tsx` in the right sidebar with target object header, export printer bed synchronization, and cut axis controls. Test: component test in `SplitPanel.test.tsx`. +- [ ] 1.2 Replace `SplitDialog` in `EditorMode.tsx` with `SplitPanel`, wiring up open/close states and active target object tracking. Verification: visual check in browser opening Split from toolbar. +- [ ] 1.3 Remove legacy `src/features/editor/cut/SplitDialog.tsx` and its test. Verification: verify build passes without dead references. + +## 2. 3D Viewport Split Preview + +- [ ] 2.1 Render printer bed boundary wireframe and translucent cut planes inside `Viewport.tsx` during split configuration. Test: render test in `Viewport.test.tsx`. +- [ ] 2.2 Add interactive 3D translation handles to cut planes allowing dragging directly on the canvas. Verification: browser check dragging a cut plane along X. +- [ ] 2.3 Render color-coded preview parts ($A1, B1, \dots$) with real-time exploded gap inspection slider. Verification: visual check in browser with 2-cut part. + +## 3. Per-Cut Connector Workflow + +- [ ] 3.1 Implement cut selector list in `SplitPanel.tsx` displaying mating part labels and dimensions for each cut interface. Test: component test in `SplitPanel.test.tsx`. +- [ ] 3.2 Update `ConnectorEditor.tsx` with orientation indicators and boundary part labels. Test: component test in `ConnectorEditor.test.tsx`. + +## 4. Version + +- [ ] 4.1 Bump `package.json` to 1.20.1 and add `1.20.1 — 44g-editor-split-panel` to `CHANGELOG.md`. Test: `npx vitest run src/site.test.ts`. + +## 5. Verification + +- [ ] 5.1 Run `npm test` and `npm run build` to ensure clean build. +- [ ] 5.2 Browser verification in EN and RU: select large body, configure split along X and Y, drag cut planes in 3D, inspect connectors, apply split, and verify created cut groups. diff --git a/openspec/changes/44h-editor-mesh-repair-wizard/.openspec.yaml b/openspec/changes/44h-editor-mesh-repair-wizard/.openspec.yaml new file mode 100644 index 0000000..c0ad5ed --- /dev/null +++ b/openspec/changes/44h-editor-mesh-repair-wizard/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-11-08 diff --git a/openspec/changes/44h-editor-mesh-repair-wizard/design.md b/openspec/changes/44h-editor-mesh-repair-wizard/design.md new file mode 100644 index 0000000..f6ace3f --- /dev/null +++ b/openspec/changes/44h-editor-mesh-repair-wizard/design.md @@ -0,0 +1,38 @@ +# Design: Visual Mesh Repair Wizard + +## Context +When users import broken STLs from third-party repositories, they need immediate visual feedback on what is broken, what the slicer will do, and whether the repair succeeded. We take UX inspiration from Sven Harzer's MeshDoc tool (licensed Source-Available, meaning we write our own algorithms clean-room and copy no code or assets) to enhance PrintKit's repair presentation. + +## Goals +- Render defect lines (open edges, non-manifold vertices) rigidly parented to the mesh in 3D. +- Present an intuitive Before ➔ After comparative audit with delta badges ($\pm\Delta$). +- Support viewport comparison modes: Original, Repaired, and Split-view. +- Calculate filament mass (g) and length (m) for PLA, PETG, ABS, and TPU. +- Provide 1-click "Drop to Bed (Z = 0)" and "Center on Bed". + +## Decisions + +### Decision 1: Clean-Room Implementation & License Compliance +MeshDoc's license permits execution but restricts code duplication and derivative works. All diagnostic extraction, hole filling, normal healing, and UI rendering are implemented independently using PrintKit's existing `geometry/mesh` code and Three.js shader overlays. MeshDoc is credited in `README.md` References as a UX design reference. + +### Decision 2: Defect Lines Overlay Layer +In `Viewport.tsx`, a specialized `DefectLines` group renders: +- Open boundary edges: `THREE.LineSegments` colored `#ef4444` (red), `depthTest: true`, with slight normal offset ($0.02\text{ mm}$) to prevent z-fighting. +- Non-manifold edges: `THREE.LineSegments` colored `#f59e0b` (amber). +These lines update automatically whenever `MeshAnalysis` completes. + +### Decision 3: Audit Report Generator (`repairAudit.ts`) +A pure function `computeRepairAudit(beforeAnalysis, afterAnalysis)` returns: +- Delta values for vertices, triangles, holes, shells, and volume. +- Slicer readiness status: `isWatertight && isManifold && volume > 0`. +- Badges formatted as e.g. `+24`, `-12`, or `0`. + +### Decision 4: Filament Estimation Calculator (`filamentEstimate.ts`) +Given solid volume $V\text{ (cm}^3)$, wall thickness factor, and infill percentage $I\in [0, 100]$: +$\text{Effective Volume } V_{\text{eff}} = V \times (0.2 + 0.8 \times \frac{I}{100})$ +$\text{Mass } m = V_{\text{eff}} \times \rho\text{ (g)}$ +$\text{Filament Length } L = \frac{V_{\text{eff}} \times 1000}{\pi \times (1.75 / 2)^2 \times 1000}\text{ (m)}$ +Densities $\rho$: PLA 1.24, PETG 1.27, ABS 1.04, TPU 1.21. + +## Risks & Mitigations +- **Overhead of dual-mesh memory during comparison:** Keeping both original and repaired meshes in memory for compare modes can consume RAM on large models. We keep the original in IndexedDB and swap GPU buffer geometries on demand when the compare toggle changes. diff --git a/openspec/changes/44h-editor-mesh-repair-wizard/proposal.md b/openspec/changes/44h-editor-mesh-repair-wizard/proposal.md new file mode 100644 index 0000000..ac74902 --- /dev/null +++ b/openspec/changes/44h-editor-mesh-repair-wizard/proposal.md @@ -0,0 +1,39 @@ +# Proposal + +## Why + +While PrintKit contains repair algorithms in `src/geometry/mesh/`, its repair user experience is disjointed and difficult for 3D printer operators to evaluate: +1. Diagnosis requires expanding nested accordions in `MeshSection.tsx` without seeing where defects are situated on the 3D model. +2. Auto-repair applies changes in-place without a clear Before vs After comparison or quantifiable metrics (delta badges showing resolved vertices, holes, and shells). +3. Operators cannot verify whether a repaired STL is ready for slicing (Bambu Studio, PrusaSlicer, OrcaSlicer, Cura) or estimate material cost (filament weight and length across PLA/PETG/ABS/TPU). + +We reference the UX workflow and visual inspection presentation of [MeshDoc](https://www.meshdoc.de/) (Sven Harzer) to upgrade PrintKit's repair interface into a visual repair wizard. Note: As MeshDoc is licensed under a Source-Available license prohibiting redistribution, no code or assets are copied or ported; all capabilities are implemented clean-room using PrintKit's existing `src/geometry/mesh/` algorithms and Three.js shaders. + +## What Changes + +- **In-Viewport Defect Visualization:** Highlight defects directly on the 3D mesh: open boundary loops in high-visibility red (`--color-danger`), non-manifold edges in yellow (`--color-warning`), and flipped triangles in tinted contrast. +- **Before / After Diagnostic Audit:** Display a comprehensive Before ➔ After comparison with exact change badges ($\pm\Delta$ vertices, triangles, holes, shells, volume, area) and a verified "100% Watertight / Manifold" status. +- **Compare Modes in Viewport:** A three-way view toggle: + - *Original*: displays the unedited imported mesh. + - *Repaired*: displays the candidate healed solid. + - *Split-View*: side-by-side or clipped comparison. +- **Deep Multi-Pass Auto-Repair:** Upgrade `autoRepair` to perform spatial vertex welding, duplicate face removal, BFS outward normal winding, unconstrained planar ear-clipping hole closure, and small shell deletion, with Make Solid fallback. +- **Slicer Readiness & Bed Placement:** Quick-action buttons to "Drop to Bed (Z = 0)" and "Center on Bed", accompanied by a slicer readiness badge for Bambu Studio, OrcaSlicer, PrusaSlicer, and Cura. +- **Filament & Material Estimator:** Automatic calculation of model weight (g) and filament length (m) for PLA ($1.24\text{ g/cm}^3$), PETG ($1.27\text{ g/cm}^3$), ABS ($1.04\text{ g/cm}^3$), and TPU ($1.21\text{ g/cm}^3$) with configurable infill percentage ($0..100\%$). + +## Capabilities + +### New Capabilities + +### Modified Capabilities +- `editor-mesh-health`: Add on-model defect wireframe overlay and slicer readiness audit with filament estimates. +- `editor-mesh-repair`: Add visual Before/After audit with delta badges, interactive compare modes (Original / Repaired / Split), and Bed drop/center helpers. + +## Impact + +- Affects `src/geometry/mesh/autoRepair.ts`, `src/features/editor/mesh/MeshSection.tsx`, `src/features/editor/mesh/AnalysisPanel.tsx`, and `src/features/viewport/Viewport.tsx`. +- Adds pure calculation modules: `src/geometry/mesh/filamentEstimate.ts` and `src/geometry/mesh/repairAudit.ts`. +- Fully backwards compatible; retains underlying Manifold and IndexedMesh pipelines. +- Target version: 1.21.0 (minor: comprehensive visual mesh repair wizard, defect overlays, and print readiness tools). +- Out of scope: Cloud mesh healing services, proprietary polygon remeshing. +- Depends on: `44a-storybook`, `44d-editor-layout-workbenches`. diff --git a/openspec/changes/44h-editor-mesh-repair-wizard/specs/editor-mesh-health/spec.md b/openspec/changes/44h-editor-mesh-repair-wizard/specs/editor-mesh-health/spec.md new file mode 100644 index 0000000..4d66a94 --- /dev/null +++ b/openspec/changes/44h-editor-mesh-repair-wizard/specs/editor-mesh-health/spec.md @@ -0,0 +1,33 @@ +# Spec Delta + +## Purpose +Specifies on-model defect highlighting, slicer readiness assessment, and filament material estimation for mesh health diagnostics. + +## MODIFIED Requirements + +### Requirement: Detailed diagnosis +For a mesh object the Editor SHALL report the number of triangles and vertices, open edges grouped into boundary loops with their perimeter, non-manifold edges and vertices, degenerate and duplicate triangles, triangles with inconsistent or flipped orientation, whether the volume is negative, the number of separate shells with their volumes, the surface area and volume, render defect lines directly on the model, assess readiness for 3D slicers, and estimate required filament weight and length. + +#### Scenario: Cube with a hole +- **WHEN** a cube with one triangle missing is analysed +- **THEN** one boundary loop of three edges is reported and the mesh is marked open + +#### Scenario: Two shells +- **WHEN** a mesh consists of a cube and a floating small sphere +- **THEN** two shells are reported with their volumes + +#### Scenario: Clean mesh +- **WHEN** the mesh is a closed manifold solid +- **THEN** the panel says it is a valid solid and shows volume and area + +#### Scenario: Defect line overlay +- **WHEN** analyzing a mesh with open loops and non-manifold edges +- **THEN** open edges are highlighted directly on the 3D surface in red and non-manifold edges in yellow + +#### Scenario: Slicer readiness audit +- **WHEN** diagnosis completes +- **THEN** the panel reports whether the model is watertight and ready for Bambu Studio, OrcaSlicer, PrusaSlicer, and Cura + +#### Scenario: Filament estimator +- **WHEN** the user selects material PLA and infill 20% +- **THEN** the calculated filament mass in grams and extrusion length in metres are displayed based on model volume diff --git a/openspec/changes/44h-editor-mesh-repair-wizard/specs/editor-mesh-repair/spec.md b/openspec/changes/44h-editor-mesh-repair-wizard/specs/editor-mesh-repair/spec.md new file mode 100644 index 0000000..c462bf9 --- /dev/null +++ b/openspec/changes/44h-editor-mesh-repair-wizard/specs/editor-mesh-repair/spec.md @@ -0,0 +1,29 @@ +# Spec Delta + +## Purpose +Specifies visual Before/After audit reporting, interactive viewport comparison modes, and print bed alignment for mesh repairs. + +## MODIFIED Requirements + +### Requirement: Auto repair +The Editor SHALL provide Auto repair that runs the standard sequence, displays a comparative Before/After audit with delta badges for all geometry metrics, offers viewport comparison modes (Original, Repaired, Split-view), and provides 1-click bed placement (Drop to Bed, Center on Bed). + +#### Scenario: Typical download +- **WHEN** Auto repair runs on a mesh with duplicate vertices, one hole and flipped normals +- **THEN** the result is a valid solid, the report lists the three fixes, and one undo restores the original + +#### Scenario: Not repairable +- **WHEN** problems remain +- **THEN** the report lists them and offers Make Solid + +#### Scenario: Before after audit badges +- **WHEN** repair completes +- **THEN** the report displays before and after values for triangles, vertices, holes, shells, and volume with positive or negative delta badges ($\pm\Delta$) + +#### Scenario: Interactive compare view +- **WHEN** switching between Original, Repaired, and Split view modes +- **THEN** the viewport dynamically toggles display between the initial broken mesh and the repaired candidate solid + +#### Scenario: Drop to bed action +- **WHEN** the user clicks Drop to Bed +- **THEN** the object translates vertically so its lowest vertex lies exactly on $Z = 0$ diff --git a/openspec/changes/44h-editor-mesh-repair-wizard/tasks.md b/openspec/changes/44h-editor-mesh-repair-wizard/tasks.md new file mode 100644 index 0000000..1afaf4e --- /dev/null +++ b/openspec/changes/44h-editor-mesh-repair-wizard/tasks.md @@ -0,0 +1,27 @@ +# Tasks + +## 1. Pure Diagnostics & Estimation Helpers + +- [ ] 1.1 Implement pure audit generator `src/geometry/mesh/repairAudit.ts` computing delta metrics ($\pm\Delta$) and slicer readiness boolean. Test: unit test in `repairAudit.test.ts`. +- [ ] 1.2 Implement pure filament mass/length calculator `src/geometry/mesh/filamentEstimate.ts` supporting PLA, PETG, ABS, and TPU with infill. Test: unit test in `filamentEstimate.test.ts`. + +## 2. 3D Viewport Defect Lines & Compare Mode + +- [ ] 2.1 Render defect lines (red open boundaries, yellow non-manifold edges) parented to the mesh in `src/features/viewport/Viewport.tsx`. Test: mock test in `Viewport.test.tsx`. +- [ ] 2.2 Implement viewport comparison toggles (Original, Repaired, Split-view) allowing interactive pre/post inspection. Verification: browser check switching views on a repaired test mesh. +- [ ] 2.3 Implement "Drop to Bed (Z = 0)" and "Center on Bed" transformation helpers in `src/features/editor/bedAlign.ts`. Test: unit test in `bedAlign.test.ts`. + +## 3. Repair Wizard UI Integration + +- [ ] 3.1 Upgrade `MeshSection.tsx` and `AnalysisPanel.tsx` to display Before/After comparative audit with delta badges and slicer readiness status. Test: component test in `MeshSection.test.tsx`. +- [ ] 3.2 Add Filament & Material Estimator card in `MeshSection.tsx` with density presets and infill slider. Verification: visual check in browser. +- [ ] 3.3 Verify license compliance: confirm no third-party code was copied from MeshDoc; add reference credit to `README.md`. Verification: code and license check. + +## 4. Version + +- [ ] 4.1 Bump `package.json` to 1.21.0 and add `1.21.0 — 44h-editor-mesh-repair-wizard` to `CHANGELOG.md`. Test: `npx vitest run src/site.test.ts`. + +## 5. Verification + +- [ ] 5.1 Run `npm test` and `npm run build` to ensure clean build. +- [ ] 5.2 Browser verification in EN and RU: import a non-manifold STL with holes, inspect on-model defect lines, run auto-repair, verify Before/After delta badges, test compare modes, and verify Drop to Bed. diff --git a/openspec/changes/45-editor-project-default/proposal.md b/openspec/changes/45-editor-project-default/proposal.md index b9ec5b6..6b4eab9 100644 --- a/openspec/changes/45-editor-project-default/proposal.md +++ b/openspec/changes/45-editor-project-default/proposal.md @@ -29,4 +29,4 @@ The editor of `39`–`44` keeps its scene in the browser's storage: it survives - Stored settings stay compatible (no migration needed); routes: `/` changes meaning and the chooser moves to `/generators` — the reason for a major version. Old deep links `#/gridfinity/box` etc. keep working. - Out of scope: cloud storage or accounts, sharing links, version history/branches of a project, merging files, embedding generator parameters as live links (the round trip replaces the mesh), WebMCP tools for the editor (a later extension of `38`), importing other CAD formats (STEP, 3MF project files of slicers), password protection. - Version 2.0.0 (major: the route `/` now opens the editor and the product chooser moves to `/generators`). -- Depends on: `43-editor-cut-split` and `44-editor-face-tools` (the complete document: cuts, stacks, faces), in the linear order of the editor series. +- Depends on: `44h-editor-mesh-repair-wizard` (the complete editor polish series).