/ simulated_instruments / woodblock
Sign in
simulated_instruments / woodblock
woodblock / webapp / src / hooks / useRenderer.ts
114 lines · 3.4 KBCodeBlameHistory
c5866daReimplement the algorithm in MATLAB syntax, run it with numblJeremy Magland 1// Hook owning the render worker: debounced auto-preview whenever the
2// parameters or the .m sources change, explicit full-quality render, and a
3// latest-wins request queue.
5import { useCallback, useEffect, useRef, useState } from 'react';
6import type { WoodblockParams } from '../params';
c5866daReimplement the algorithm in MATLAB syntax, run it with numblJeremy Magland 7import type { MFile } from '../mfiles';
8import type { ErrorMessage, ProgressMessage, RenderResponse } from '../worker/renderWorker';
10export interface RenderError {
11 message: string;
12 file?: string;
13 line?: number;
16export interface RenderState {
17 result: RenderResponse | null;
c5866daReimplement the algorithm in MATLAB syntax, run it with numblJeremy Magland 18 error: RenderError | null;
20 stage: string;
21 progress: number; // 0..1 of the current stage
25 params: WoodblockParams;
26 mfiles: MFile[];
27 quality: 'preview' | 'full';
30export function useRenderer(params: WoodblockParams, mfiles: MFile[]) {
982850fWoodblock strike simulator: Python reference model and interactive web appJeremy Magland 31 const workerRef = useRef<Worker | null>(null);
32 const nextId = useRef(1);
33 const inFlight = useRef<number | null>(null);
c5866daReimplement the algorithm in MATLAB syntax, run it with numblJeremy Magland 34 const queued = useRef<Request | null>(null);
35 const sendRef = useRef<(r: Request) => void>(() => {});
982850fWoodblock strike simulator: Python reference model and interactive web appJeremy Magland 36 const [state, setState] = useState<RenderState>({
37 result: null,
40 stage: '',
41 progress: 0,
42 });
c5866daReimplement the algorithm in MATLAB syntax, run it with numblJeremy Magland 44 const send = useCallback((req: Request) => {
45 const worker = workerRef.current;
46 if (!worker) return;
47 if (inFlight.current !== null) {
48 queued.current = req; // latest wins
49 return;
50 }
51 const id = nextId.current++;
52 inFlight.current = id;
53 setState((s) => ({ ...s, busy: true, stage: 'starting', progress: 0 }));
54 worker.postMessage({ type: 'render', id, ...req });
55 }, []);
56 sendRef.current = send;
59 const worker = new Worker(new URL('../worker/renderWorker.ts', import.meta.url), {
60 type: 'module',
61 });
62 workerRef.current = worker;
64 const finish = (update: (s: RenderState) => RenderState) => {
65 inFlight.current = null;
66 const next = queued.current;
67 queued.current = null;
68 setState((s) => {
69 const done = update(s);
70 return next ? { ...done, busy: true, stage: 'queued', progress: 0 } : done;
71 });
72 if (next) sendRef.current(next);
73 };
75 worker.onmessage = (ev: MessageEvent<RenderResponse | ProgressMessage | ErrorMessage>) => {
77 if (msg.type === 'progress') {
78 setState((s) => ({ ...s, stage: msg.stage, progress: msg.frac }));
79 return;
80 }
c5866daReimplement the algorithm in MATLAB syntax, run it with numblJeremy Magland 81 if (msg.type === 'error') {
82 // Keep the last good result on screen; the code panel shows the fault.
83 finish((s) => ({
84 ...s,
85 error: { message: msg.message, file: msg.file, line: msg.line },
86 busy: false,
87 stage: '',
88 progress: 0,
89 }));
90 return;
c5866daReimplement the algorithm in MATLAB syntax, run it with numblJeremy Magland 92 finish(() => ({ result: msg, error: null, busy: false, stage: '', progress: 0 }));
94 return () => {
95 worker.terminate();
96 workerRef.current = null;
c5866daReimplement the algorithm in MATLAB syntax, run it with numblJeremy Magland 97 inFlight.current = null;
98 queued.current = null;
100 }, []);
c5866daReimplement the algorithm in MATLAB syntax, run it with numblJeremy Magland 102 const renderFull = useCallback(
103 () => send({ params, mfiles, quality: 'full' }),
104 [params, mfiles, send],
105 );
c5866daReimplement the algorithm in MATLAB syntax, run it with numblJeremy Magland 107 // Debounced auto-preview on any change to the parameters or the code.
c5866daReimplement the algorithm in MATLAB syntax, run it with numblJeremy Magland 109 const t = setTimeout(() => send({ params, mfiles, quality: 'preview' }), 250);
982850fWoodblock strike simulator: Python reference model and interactive web appJeremy Magland 110 return () => clearTimeout(t);
c5866daReimplement the algorithm in MATLAB syntax, run it with numblJeremy Magland 111 }, [params, mfiles, send]);
113 return { ...state, renderFull };
↑↓ move↵openescclose