// CompositeLayerControlPanel: render a shader's `*_CONTROLS` descriptor list as // fields, in order, data-driven. This is the AUTO-FORM (the default when a shader // ships no custom layout form): ``. // It maps every descriptor through the shared `dispatchControl`, so it handles // every kind (color, float, switch, polygon) the same way `` does. // // KaleidoscopePreset-level customization is props: pass a filtered `controls` // array to hide knobs, or `overrides` to narrow a control's range/label for this // composite. For real layout (grouping, split, per-beam lists), a shader exports // a custom form of ``s instead of using this panel. import { Fragment } from 'react'; import type { UniformControl } from '../../../catalog/shaders'; import { dispatchControl } from './control'; /** Per-uniform range/label override, keyed by uniform name. */ export type ControlOverride = { readonly min?: number; readonly max?: number; readonly step?: number; readonly label?: string; }; export type CompositeLayerControlPanelProps = { readonly controls: readonly UniformControl[]; readonly overrides?: Readonly>; }; // Merge a preset override onto a descriptor. min/max/step only apply to float; // label applies to any kind. function withOverride(c: UniformControl, o?: ControlOverride): UniformControl { if (!o) return c; if (c.kind === 'float') { return { ...c, min: o.min ?? c.min, max: o.max ?? c.max, step: o.step ?? c.step, label: o.label ?? c.label, }; } return o.label ? { ...c, label: o.label } : c; } export function CompositeLayerControlPanel({ controls, overrides, }: CompositeLayerControlPanelProps) { return ( <> {controls.map((c) => ( {dispatchControl(withOverride(c, overrides?.[c.name]))} ))} ); }