MoveTool: dispatch by capabilities.movable, not nodeRegistry.has
User report: after wall registered, the move tool's smart sims-style
arrow UX (endpoint handles + linked-wall corner cascade + ALT-detach)
was replaced by a generic whole-wall-translate. The dispatch was
unconditionally routing every registered kind through
MoveRegistryNodeTool — but MoveRegistryNodeTool is for kinds whose
move semantics are "translate position on X/Z plane" (shelf, spawn,
single-position items). Wall / fence / slab / stair endpoint drags
are bespoke and need their legacy movers until each gets a proper
DragAction-based affordance port.
Fix: gate the registry-mover dispatch on `def.capabilities.movable`.
When a kind opts in (`movable: { axes, gridSnap }`), use the generic
mover; when a kind omits the capability deliberately (wall and fence
do), fall through to the legacy per-kind branch below.
This is the registry-aware analogue of "the registry doesn't limit
custom behavior — it lets kinds opt in to generic dispatch". Adding
`movable` is an opt-in; omitting it is an opt-out.
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
71b211de97
commit
fc9a5d02a0
@@ -103,13 +103,22 @@ export const MoveTool: React.FC<{
|
|||||||
|
|
||||||
if (!movingNode) return null
|
if (!movingNode) return null
|
||||||
|
|
||||||
// Registry-first dispatch. Any kind registered via @pascal-app/nodes
|
// Capability-driven dispatch. A registered kind opts INTO the generic
|
||||||
// gets the imperative MoveRegistryNodeTool (smooth, framerate-locked
|
// mover by declaring `capabilities.movable` — that's the "I'm a simple
|
||||||
// motion via sceneRegistry — see plan: "Validated patterns from the
|
// translate-on-the-X/Z-plane node" signal (shelf, spawn, future
|
||||||
// spike"). The legacy per-kind movers below are short-circuited for
|
// single-position items). Kinds with bespoke move semantics (wall
|
||||||
// any kind in the registry — that's how Phase 5 will progressively
|
// endpoint drag + linked-wall corner cascade + ALT-detach, fence
|
||||||
// delete them as kinds migrate.
|
// endpoint drag + curve sagitta, slab polygon vertex edit, stair
|
||||||
if (nodeRegistry.has(movingNode.type)) {
|
// endpoint drag, etc.) deliberately OMIT `capabilities.movable` so
|
||||||
|
// this branch falls through to their legacy per-kind movers below.
|
||||||
|
//
|
||||||
|
// Without this guard, every registered kind would be force-routed
|
||||||
|
// through MoveRegistryNodeTool's "translate position" pattern,
|
||||||
|
// breaking wall / fence / slab / stair endpoint UX (the smart
|
||||||
|
// sims-style arrows that move the dragged endpoint while cascading
|
||||||
|
// to linked walls / re-anchoring hosted children / etc.).
|
||||||
|
const def = nodeRegistry.get(movingNode.type)
|
||||||
|
if (def?.capabilities?.movable) {
|
||||||
return <MoveRegistryNodeTool node={movingNode} />
|
return <MoveRegistryNodeTool node={movingNode} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user