parametrics: add custom field kind + restore fence Length / Curve
User noticed the auto-derived fence inspector was missing the legacy
panel's Length + Curve sliders, and the section labelling was wrong
(Posts → Structure). Both Length and Curve are awkward for the
parametrics field model:
- **Length** doesn't map to a single node key — it's derived from
`start`/`end`, and editing it moves `end` along the existing
direction.
- **Curve** maps to `curveOffset` but the slider's min/max are
bounded per-node by the chord length, plus updates need
`normalizeWallCurveOffset`.
Adds a `kind: 'custom'` field with a kind-supplied
`component: ComponentType<{ node, onUpdate }>`. The inspector mounts
it and lets the kind own rendering + update logic. `key` becomes a
free-form React key/label since it no longer needs to map to a node
property.
Fence parametrics now mirrors the legacy layout 1:1:
- Style (segmented controls + showInfill toggle).
- Dimensions (Length, Curve, Height, Thickness).
- Structure (Base Height, Top Rail, Post Spacing, Post Size, Ground
Clear, Edge Inset).
Length + Curve live in fence/inspector-editors.tsx.
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
80199dc890
commit
282cb22585
@@ -293,12 +293,35 @@ function FieldRenderer({ field, nodeId, onUpdate }: FieldRendererProps) {
|
||||
)
|
||||
}
|
||||
|
||||
case 'custom':
|
||||
// The field owns its rendering and update logic — used for
|
||||
// derived values (length from start/end), dynamic-bounded
|
||||
// sliders (curve sagitta), composed editors.
|
||||
return <CustomFieldRenderer Comp={field.component} nodeId={nodeId} onUpdate={onUpdate} />
|
||||
|
||||
default:
|
||||
// material / ref / unrecognized kinds — not implemented in v1.
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function CustomFieldRenderer({
|
||||
Comp,
|
||||
nodeId,
|
||||
onUpdate,
|
||||
}: {
|
||||
Comp: ComponentType<{ node: AnyNode; onUpdate: (patch: Partial<AnyNode>) => void }>
|
||||
nodeId: AnyNodeId
|
||||
onUpdate: (patch: Partial<AnyNode>) => void
|
||||
}) {
|
||||
// Subscribe to the full node — the custom editor may read any
|
||||
// field. Tools that don't want this churn should write narrower
|
||||
// selectors inside Comp itself.
|
||||
const node = useScene((s) => s.nodes[nodeId])
|
||||
if (!node) return null
|
||||
return <Comp node={node} onUpdate={onUpdate} />
|
||||
}
|
||||
|
||||
// ─── helpers ─────────────────────────────────────────────────────────
|
||||
|
||||
function precisionForStep(step: number): number {
|
||||
|
||||
Reference in New Issue
Block a user