|
1 | 1 | import type * as d from 'typegpu/data'; |
| 2 | +import { useRoot } from './root-context.tsx'; |
| 3 | +import { useEffect, useMemo, useRef, useState } from 'react'; |
| 4 | +import type { ValidateUniformSchema } from 'typegpu'; |
2 | 5 |
|
3 | 6 | interface UniformValue<TSchema, TValue extends d.Infer<TSchema>> { |
4 | 7 | schema: TSchema; |
5 | | - value: TValue; |
| 8 | + value: TValue | undefined; |
| 9 | + readonly $: d.InferGPU<TSchema>; |
6 | 10 | } |
7 | 11 |
|
8 | | -export function useUniformValue<TSchema, TValue extends d.Infer<TSchema>>( |
9 | | - schema: d.AnyWgslData, |
| 12 | +export function useUniformValue< |
| 13 | + TSchema extends d.AnyWgslData, |
| 14 | + TValue extends d.Infer<TSchema>, |
| 15 | +>( |
| 16 | + schema: ValidateUniformSchema<TSchema>, |
10 | 17 | initialValue?: TValue | undefined, |
11 | 18 | ): UniformValue<TSchema, TValue> { |
12 | | - // TODO: Implement |
| 19 | + const root = useRoot(); |
| 20 | + |
| 21 | + const [uniformBuffer] = useState(() => { |
| 22 | + return root.createUniform( |
| 23 | + schema, |
| 24 | + initialValue, |
| 25 | + ); |
| 26 | + }); |
| 27 | + |
| 28 | + const cleanupRef = useRef<ReturnType<typeof setTimeout> | null>(null); |
| 29 | + useEffect(() => { |
| 30 | + if (cleanupRef.current) { |
| 31 | + clearTimeout(cleanupRef.current); |
| 32 | + } |
| 33 | + |
| 34 | + return () => { |
| 35 | + cleanupRef.current = setTimeout(() => { |
| 36 | + uniformBuffer.buffer.destroy(); |
| 37 | + }, 200); |
| 38 | + }; |
| 39 | + }, [uniformBuffer]); |
| 40 | + |
| 41 | + // biome-ignore lint/correctness/useExhaustiveDependencies: This value needs to be stable |
| 42 | + const uniformValue = useMemo(() => { |
| 43 | + let currentValue = initialValue; |
| 44 | + return { |
| 45 | + schema, |
| 46 | + get value() { |
| 47 | + return currentValue; |
| 48 | + }, |
| 49 | + set value(newValue: TValue | undefined) { |
| 50 | + currentValue = newValue; |
| 51 | + if (newValue !== undefined) { |
| 52 | + uniformBuffer.write(newValue); |
| 53 | + } |
| 54 | + }, |
| 55 | + get $() { |
| 56 | + return uniformBuffer.$; |
| 57 | + }, |
| 58 | + }; |
| 59 | + }, []); |
| 60 | + |
| 61 | + return uniformValue as UniformValue<TSchema, TValue>; |
13 | 62 | } |
0 commit comments