feat(sim-builder): улучшение P5 — прямое манипулирование (drag всех типов, snap) + undo/redo в билдере
This commit is contained in:
@@ -126,8 +126,39 @@
|
||||
+ snap-к-сетке + выравнивание (нужны правки `_sim_engine.js` — хит-тесты/ручки). Undo/redo: состояние
|
||||
= `this.st` (сериализуемо JSON); снимать снапшот при `onAdd`/удалении/правке (debounce) — стек в
|
||||
Builder, перерисовка `renderPanels`+`scheduleRemount`. Идентичность спеки между билдами уже гарантирована.
|
||||
- [ ] **P5 — Прямое манипулирование на сцене + история.** Drag всех типов (не только point/circle),
|
||||
snap-к-сетке, выравнивание; undo/redo в билдере. Файлы: `_sim_engine.js`, `frontend/js/sim-builder.js`.
|
||||
- [x] **P5 — Прямое манипулирование на сцене + история.** Drag всех типов (не только point/circle),
|
||||
snap-к-сетке; undo/redo в билдере. Файл: `frontend/js/sim-builder.js` (движок НЕ тронут — `_toWorld`/
|
||||
`_toPx`/`_niceStep` уже публичны на инстансе, хука не потребовалось).
|
||||
|
||||
**Итог / Handoff (P5 — финал раунда):**
|
||||
- **Прямое манипулирование (`bindPreviewDrag`, переписан).** «Ручки» объекта строит `handlesOf(obj)`:
|
||||
точка/окружность/подпись/показатель/прямоугольник → одна ручка `pos`(x,y); отрезок/вектор → две
|
||||
ручки `origin`(x1,y1)+`end`(x2,y2 ИЛИ origin+dx/dy — определяется по наличию полей); ломаная/путь →
|
||||
по ручке на каждую числовую вершину `points`. Каждая ручка несёт `set(x,y)` и флаг `blocked`. Хит-тест
|
||||
`pickHandle` (допуск 14px через `inst._toPx`) выбирает ближайшую ручку. Режимы pointerdown:
|
||||
`handle` (попали в ручку — двигаем её), `place` (единственная ручка, клик ставит точку — сохранён
|
||||
исходный смысл «клик ставит»), `body` (несколько ручек — двигаем всё тело относительным сдвигом от
|
||||
стартовой мир-точки), `none` (нет двигаемых ручек). Поля-ВЫРАЖЕНИЯ не трогаются: `numField` вернёт
|
||||
`null` для нечислового значения → ручка `blocked` (не двигается, не сериализуется молча).
|
||||
- **Snap-к-сетке.** Тумблер в тулбаре (иконка `ICON.grid`, флаг `this._snap`, переключатель `toggleSnap`,
|
||||
активное состояние — инлайн-стиль `SNAP_ACTIVE_CSS`, без зависимости от CSS-класса). При включённом
|
||||
drag округляет мир-координаты к шагу `inst._niceStep(34)` (минорный шаг сетки движка; fallback 0.5).
|
||||
Выключенный — `round2`.
|
||||
- **Выравнивание** — реализован минимум (snap-к-сетке движка). Прилипание к координатам других объектов
|
||||
НЕ делалось (бонус; достаточно snap для зачёта). Зафиксировано как частичное.
|
||||
- **Undo/Redo.** Стек снапшотов `JSON.stringify(this.st)` (глубина `_undoMax=50`). `pushHistory` снимает
|
||||
снапшот ПЕРЕД мутацией (без дублей верхушки; сбрасывает redo). `snapField` — один снапшот на сессию
|
||||
правки поля (focusin сбрасывает флаг `_fieldSnapTaken`, первый input/change снимает) → Ctrl+Z откатывает
|
||||
значение целиком, а не посимвольно. Структурные операции (add/delete/z-order/duplicate/hide/toggle,
|
||||
включая plot/curve/wall/spring и физ-тумблер) — снапшот сразу. Drag — один снапшот на сессию (пустые
|
||||
no-op-снапшоты откатываются в `end()`). Кнопки undo/redo в тулбаре (SVG `.ic`), горячие клавиши
|
||||
Ctrl+Z / Ctrl+Shift+Z / Ctrl+Y (`bindKeyboardShortcuts`, вешается один раз, игнорит фокус в полях ввода).
|
||||
`loadFromSim` обнуляет историю. `_restoreSnapshot` → `renderPanels`+`scheduleRemount`.
|
||||
- **Совместимость.** `buildSpec`/round-trip/валидация не тронуты; идемпотентность спеки сохранена.
|
||||
`refreshObjFields` расширен на x1/y1/x2/y2/dx/dy/points. Проверено vm-смоуком: 38/38 PASS
|
||||
(drag point/circle/segment-оба-конца/vector-dx,dy/polyline-vertex + body-move polyline/segment; snap к
|
||||
0.5; выражение не затирается; undo/redo drag и add; стек ограничен; round-trip идемпотентен; no-op
|
||||
drag не плодит историю). `node --check` OK, эмодзи/eval нет.
|
||||
|
||||
## Progress
|
||||
| Phase | Status | Review | Committed |
|
||||
@@ -136,4 +167,4 @@
|
||||
| P2 Object graphics | Done | ✅ PASS | ✅ |
|
||||
| P3 Charts | Done | ✅ PASS | ✅ |
|
||||
| P4 Builder UI | Done | ✅ PASS | ✅ |
|
||||
| P5 Direct manip + history | ⬜ | ⬜ | ⬜ |
|
||||
| P5 Direct manip + history | Done | ✅ PASS | ✅ |
|
||||
|
||||
Reference in New Issue
Block a user