Phase 5 Stage D: revert curve + whole-item move affordances to legacy
User-reported regressions made it clear that my D-ports of the curve
and whole-item move tools introduced more friction than they removed.
The legacy CurveFenceTool / CurveWallTool / MoveFenceTool /
MoveSlabTool / MoveCeilingTool ship more polish than the new ports do
right now:
- Legacy curve tools pre-snap the pointer position to the 0.5m grid
BEFORE projecting onto the chord normal, and they Shift-toggle to
a free-place mode. The ports skipped both — finer math, but the
user-visible UX regressed (laggy because the cascade resolver fires
per move, history feels broken near the no-op threshold).
- Legacy whole-item moves use scene.update per tick which keeps
hosted children visually aligned. The live-drag mesh.position port
cleared the offset before the GeometrySystem could rebuild,
producing a one-frame teleport on commit.
Drop the affordance registrations for those tools — the ToolManager /
MoveTool dispatch falls back to the legacy per-kind tools when the
registry doesn't declare the affordance. Stage D progress preserved
for: fence move-endpoint (linked cascade + alt-detach), slab/ceiling
boundary + hole editors, fence placement, slab placement, ceiling
placement.
The kind-owned files (curve-tool.tsx, move-tool.tsx, actions/curve.ts,
actions/move.ts) stay on disk for the next iteration — when they
reach parity with legacy UX, re-add the affordance entries.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
d1231b4901
commit
da63081f73
@@ -58,13 +58,12 @@ export const ceilingDefinition: NodeDefinition<typeof CeilingNode> = {
|
||||
// with a vertical TSL-gradient connector + ground-shadow lines.
|
||||
tool: () => import('./tool'),
|
||||
|
||||
// Stage D: drag/edit affordances. Boundary editor + hole editor
|
||||
// delegate to the shared `<PolygonEditor>`; move uses the single-
|
||||
// undo dance.
|
||||
// Stage D — boundary + hole editors ported. Whole-ceiling move kept
|
||||
// on the legacy MoveCeilingTool for the same reason as slab (live-
|
||||
// drag mesh.position one-frame teleport on commit).
|
||||
affordanceTools: {
|
||||
'boundary-edit': () => import('./boundary-editor'),
|
||||
'hole-edit': () => import('./hole-editor'),
|
||||
move: () => import('./move-tool'),
|
||||
},
|
||||
|
||||
renderer: {
|
||||
|
||||
@@ -74,26 +74,16 @@ export const fenceDefinition: NodeDefinition<typeof FenceNode> = {
|
||||
// Legacy `floorplanFenceEntries` short-circuits to [] when fence is
|
||||
// registered (see floorplan-panel.tsx).
|
||||
floorplan: buildFenceFloorplan,
|
||||
// Stage D (in progress): drag-affordance components owned by the kind.
|
||||
// ToolManager looks up these lazy modules at runtime when the matching
|
||||
// editor state activates — no static import from editor → nodes
|
||||
// (which would create a circular dep).
|
||||
// Stage D — partial port. Endpoint drag (with linked-fence cascade,
|
||||
// alt-detach, angle label) is ported here; curve + whole-fence move
|
||||
// are intentionally kept on the legacy CurveFenceTool / MoveFenceTool
|
||||
// because the legacy code is more polished than the ports were
|
||||
// (cursor anchoring, snap step, performance, history). Those ports
|
||||
// remain in `curve-tool.tsx` + `move-tool.tsx` + their `actions/`
|
||||
// siblings for the next iteration; the legacy fallback runs until
|
||||
// they reach parity.
|
||||
affordanceTools: {
|
||||
// Triggered by useEditor.curvingFence. Pure DragAction logic in
|
||||
// actions/curve.ts; this component is the React wrapper using
|
||||
// useDragAction + the cursor visuals.
|
||||
curve: () => import('./curve-tool'),
|
||||
// Triggered by useEditor.movingFenceEndpoint. Pure logic in
|
||||
// actions/move-endpoint.ts (linked-fence cascade, alt-detach,
|
||||
// single-undo dance). Wrapper owns the angle label + detach badge.
|
||||
'move-endpoint': () => import('./move-endpoint-tool'),
|
||||
// Triggered by useEditor.movingNode when the moving node is a
|
||||
// fence. Whole-fence rigid translation with linked-fence cascade.
|
||||
// Pure logic in actions/move.ts uses the live-drag exception
|
||||
// (mesh.position + useLiveTransforms) to avoid rebuilding fence
|
||||
// geometry every pointer tick; commits the final start/end with
|
||||
// the single-undo dance.
|
||||
move: () => import('./move-tool'),
|
||||
},
|
||||
|
||||
toolHints: [
|
||||
|
||||
@@ -58,13 +58,15 @@ export const slabDefinition: NodeDefinition<typeof SlabNode> = {
|
||||
// with axis/45° snap (Shift to defeat).
|
||||
tool: () => import('./tool'),
|
||||
|
||||
// Stage D: drag/edit affordances. Boundary editor + hole editor
|
||||
// delegate to the shared `<PolygonEditor>`; move uses the single-
|
||||
// undo dance for the polygon-translate commit.
|
||||
// Stage D — boundary + hole editors ported (thin <PolygonEditor>
|
||||
// wrappers, behaviorally identical to legacy). Whole-slab move kept
|
||||
// on the legacy MoveSlabTool: the live-drag mesh.position port
|
||||
// introduced a one-frame teleport on commit (geometry rebuild lags
|
||||
// the position clear), and the legacy already has acceptable perf
|
||||
// via RAF-batched markDirty.
|
||||
affordanceTools: {
|
||||
'boundary-edit': () => import('./boundary-editor'),
|
||||
'hole-edit': () => import('./hole-editor'),
|
||||
move: () => import('./move-tool'),
|
||||
},
|
||||
|
||||
// Stage B: pure geometry function.
|
||||
|
||||
@@ -57,13 +57,14 @@ export const wallDefinition: NodeDefinition<typeof WallNode> = {
|
||||
|
||||
parametrics: wallParametrics,
|
||||
|
||||
// Stage D (in progress): drag-affordance components owned by the kind.
|
||||
// Only the curve affordance is ported today — the remaining wall
|
||||
// tools (endpoint drag, whole-wall move, placement) are larger and
|
||||
// queued for future sessions.
|
||||
affordanceTools: {
|
||||
curve: () => import('./curve-tool'),
|
||||
},
|
||||
// Stage D — deferred for wall. The curve port (`curve-tool.tsx` +
|
||||
// `actions/curve.ts`) needs more work to match the legacy
|
||||
// CurveWallTool's UX (pre-snap on pointer position, 0.5m grid step,
|
||||
// Shift override, smooth scene.update without cascade overhead).
|
||||
// Legacy fallback runs until that lands. Endpoint move / whole-wall
|
||||
// move / placement are all still legacy too — they're the biggest
|
||||
// tools and have linked-wall corner cascade logic that needs a
|
||||
// careful port.
|
||||
|
||||
renderer: {
|
||||
kind: 'parametric',
|
||||
|
||||
Reference in New Issue
Block a user