Skip to content

Commit d3b4bf2

Browse files
fix: Vector slider controls (#2247)
1 parent 830b5af commit d3b4bf2

6 files changed

Lines changed: 58 additions & 43 deletions

File tree

apps/typegpu-docs/src/components/ControlPanel.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ function SliderRow({
8888
);
8989
}
9090

91-
function VectorSliderRow({
91+
function VectorSliderRow<T extends d.v2f | d.v3f | d.v4f>({
9292
label,
9393
initial,
9494
min,
@@ -97,13 +97,13 @@ function VectorSliderRow({
9797
onChange,
9898
}: {
9999
label: string;
100-
initial: number[];
101-
min: number[];
102-
max: number[];
103-
step: number[];
104-
onChange: (value: number[]) => void;
100+
initial: T;
101+
min: T;
102+
max: T;
103+
step: T;
104+
onChange: (value: T) => void;
105105
}) {
106-
const [value, setValue] = useState<number[]>(initial ?? min);
106+
const [value, setValue] = useState<T>(initial);
107107
const runWithCatch = useSetAtom(runWithCatchAtom);
108108

109109
return (
@@ -116,8 +116,8 @@ function VectorSliderRow({
116116
step={step}
117117
value={value}
118118
onChange={(newValue) => {
119-
setValue(newValue);
120-
void runWithCatch(() => onChange(newValue));
119+
setValue(newValue as T);
120+
void runWithCatch(() => onChange(newValue as T));
121121
}}
122122
/>
123123
</>
@@ -248,7 +248,7 @@ function paramToControlRow(param: ExampleControlParam) {
248248
<VectorSliderRow
249249
key={param.label}
250250
label={param.label}
251-
onChange={param.onVectorSliderChange}
251+
onChange={param.onVectorSliderChange as (value: d.v2f | d.v3f | d.v4f) => void}
252252
min={param.min}
253253
max={param.max}
254254
step={param.step}

apps/typegpu-docs/src/components/design/VectorSlider.tsx

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
import * as RadixSlider from '@radix-ui/react-slider';
2+
import { d } from 'typegpu';
23

3-
type Props = {
4-
min: number[];
5-
max: number[];
6-
step: number[];
7-
value: number[];
8-
onChange: (value: number[]) => void;
4+
type Props<T extends d.v2f | d.v3f | d.v4f> = {
5+
min: T;
6+
max: T;
7+
step: T;
8+
value: T;
9+
onChange: (value: T) => void;
910
};
1011

11-
export function VectorSlider({ min, max, step, value, onChange }: Props) {
12+
export function VectorSlider({ min, max, step, value, onChange }: Props<d.v2f | d.v3f | d.v4f>) {
1213
const handleComponentChange = (index: number, newValue: number) => {
13-
onChange([...value.slice(0, index), newValue, ...value.slice(index + 1)]);
14+
const newVec =
15+
value.kind === 'vec2f'
16+
? d.vec2f(value)
17+
: value.kind === 'vec3f'
18+
? d.vec3f(value)
19+
: d.vec4f(value);
20+
newVec[index] = newValue;
21+
onChange(newVec);
1422
};
1523

1624
const renderSlider = (index: number) => (

apps/typegpu-docs/src/components/stackblitz/stackBlitzIndex.ts

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { d } from 'typegpu';
2+
13
const body = document.querySelector('body') as HTMLBodyElement;
24
body.style.display = 'flex';
35
body.style.flexDirection = 'column';
@@ -146,15 +148,15 @@ for (const controls of Object.values(example)) {
146148

147149
slider.addEventListener('input', () => {
148150
currentValues[i] = Number.parseFloat(slider.value);
149-
params.onVectorSliderChange(currentValues);
151+
(params.onVectorSliderChange as (value: d.v2f | d.v3f | d.v4f) => void)(currentValues);
150152
});
151153

152154
row.appendChild(labelSpan);
153155
row.appendChild(slider);
154156
sliderContainer.appendChild(row);
155157
}
156158

157-
params.onVectorSliderChange(currentValues);
159+
(params.onVectorSliderChange as (value: d.v2f | d.v3f | d.v4f) => void)(currentValues);
158160
controlRow.appendChild(sliderContainer);
159161
}
160162

@@ -222,17 +224,17 @@ type SliderControlParam = {
222224
step?: number;
223225
};
224226

225-
type VectorSliderControlParam = {
226-
onVectorSliderChange: (newValue: number[]) => void;
227-
initial: number[];
228-
min: number[];
229-
max: number[];
230-
step: number[];
227+
type VectorSliderControlParam<T extends d.v2f | d.v3f | d.v4f> = {
228+
onVectorSliderChange: (newValue: T) => void;
229+
initial: T;
230+
min: T;
231+
max: T;
232+
step: T;
231233
};
232234

233235
type ColorPickerControlParam = {
234-
onColorChange: (newValue: readonly [number, number, number]) => void;
235-
initial: readonly [number, number, number];
236+
onColorChange: (newValue: d.v3f) => void;
237+
initial: d.v3f;
236238
};
237239

238240
type ButtonControlParam = {
@@ -250,22 +252,24 @@ type ExampleControlParam =
250252
| SliderControlParam
251253
| ButtonControlParam
252254
| TextAreaControlParam
253-
| VectorSliderControlParam
255+
| VectorSliderControlParam<d.v2f>
256+
| VectorSliderControlParam<d.v3f>
257+
| VectorSliderControlParam<d.v4f>
254258
| ColorPickerControlParam;
255259

256-
function hexToRgb(hex: string): readonly [number, number, number] {
257-
return [
260+
function hexToRgb(hex: string): d.v3f {
261+
return d.vec3f(
258262
Number.parseInt(hex.slice(1, 3), 16) / 255,
259263
Number.parseInt(hex.slice(3, 5), 16) / 255,
260264
Number.parseInt(hex.slice(5, 7), 16) / 255,
261-
];
265+
);
262266
}
263267

264268
function componentToHex(c: number) {
265269
const hex = (c * 255).toString(16);
266270
return hex.length === 1 ? `0${hex}` : hex;
267271
}
268272

269-
function rgbToHex(rgb: readonly [number, number, number]) {
273+
function rgbToHex(rgb: d.v3f) {
270274
return `#${rgb.map(componentToHex).join('')}`;
271275
}

apps/typegpu-docs/src/examples/rendering/phong-reflection/params.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { ExampleControls } from './schemas.ts';
44
export const backgroundColor = d.vec3f(28, 28, 28).div(255);
55

66
export const initialControls = ExampleControls({
7-
lightColor: d.vec3f(1, 0.7, 0),
7+
lightColor: d.vec3f(0.8, 0.8, 0.8),
88
lightDirection: d.vec3f(0, 7, -7),
9-
ambientColor: d.vec3f(0.6, 0.6, 0.6),
9+
ambientColor: d.vec3f(1, 0.7, 0),
1010
ambientStrength: 0.5,
1111
specularExponent: 8,
1212
});

apps/typegpu-docs/src/utils/examples/exampleControlAtom.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ export type SliderControlParam = {
2323
label: string;
2424
};
2525

26-
export type VectorSliderControlParam = {
27-
onVectorSliderChange: (newValue: number[]) => void;
28-
initial: number[];
29-
min: number[];
30-
max: number[];
31-
step: number[];
26+
export type VectorSliderControlParam<T extends d.v2f | d.v3f | d.v4f> = {
27+
onVectorSliderChange: (newValue: T) => void;
28+
initial: T;
29+
min: T;
30+
max: T;
31+
step: T;
3232
label: string;
3333
};
3434

@@ -55,7 +55,9 @@ export type ExampleControlParam =
5555
| SliderControlParam
5656
| ButtonControlParam
5757
| TextAreaControlParam
58-
| VectorSliderControlParam
58+
| VectorSliderControlParam<d.v2f>
59+
| VectorSliderControlParam<d.v3f>
60+
| VectorSliderControlParam<d.v4f>
5961
| ColorPickerControlParam;
6062

6163
export const exampleControlsAtom = atom<ExampleControlParam[]>([]);

apps/typegpu-docs/src/utils/examples/exampleRunner.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { d } from 'typegpu';
12
import type { ExampleControlParam } from './exampleControlAtom.ts';
23
import type { ExampleState } from './exampleState.ts';
34

@@ -14,7 +15,7 @@ function initializeParam(param: ExampleControlParam) {
1415
return param.onSliderChange(param.initial);
1516
}
1617
if ('onVectorSliderChange' in param) {
17-
return param.onVectorSliderChange(param.initial);
18+
return (param.onVectorSliderChange as (v: d.v2f | d.v3f | d.v4f) => void)(param.initial);
1819
}
1920
if ('onColorChange' in param) {
2021
return param.onColorChange(param.initial);

0 commit comments

Comments
 (0)