Split paint/render image to handle callback depth

Iterator state still uses the same pattern, not sure how problematic that is.
This commit is contained in:
Bradlee Speice 2024-11-30 12:39:54 -05:00
parent 12c88ef8e3
commit 1aa45e3f59

View File

@ -55,29 +55,28 @@ export default function Canvas({width, height, children}: CanvasProps) {
} }
}, []); }, []);
const {colorMode} = useColorMode();
// Holder objects are used to force re-painting even if the iterator // Holder objects are used to force re-painting even if the iterator
// returns a modified image with the same reference // returns a modified image with the same reference
type ImageHolder = { image?: ImageData }; type ImageHolder = { image?: ImageData };
const [imageHolder, setImageHolder] = useState<ImageHolder>({ image: null });
useEffect(() => {
const image = imageHolder.image;
if (!image) {
// No image is available, leave the canvas as-is
return;
}
if (!canvasCtx) { const [paintImage, setPaintImage] = useState<ImageHolder>({ image: null });
// Canvas is not ready for the image we have, useEffect(() => {
// re-submit the image and wait for the ref to populate if (paintImage.image && canvasCtx) {
setImageHolder({ image }); canvasCtx.putImageData(paintImage.image, 0, 0);
}
}, [paintImage, canvasCtx]);
const {colorMode} = useColorMode();
const [renderImage, setRenderImage] = useState<ImageHolder>({ image: null });
useEffect(() => {
const image = renderImage.image;
if (!image) {
return; return;
} }
// If light mode is active, paint the image as-is // If light mode is active, paint the image as-is
if (colorMode === 'light') { if (colorMode === 'light') {
canvasCtx.putImageData(image, 0, 0); setPaintImage({ image });
return; return;
} }
@ -89,8 +88,8 @@ export default function Canvas({width, height, children}: CanvasProps) {
const isAlpha = index % 4 === 3; const isAlpha = index % 4 === 3;
paintImage.data[index] = isAlpha ? value : 255 - value; paintImage.data[index] = isAlpha ? value : 255 - value;
}) })
canvasCtx.putImageData(paintImage, 0, 0); setPaintImage({ image: paintImage });
}, [colorMode, imageHolder]); }, [colorMode, renderImage]);
// Image iterators (painters) are also in a holder; this allows // Image iterators (painters) are also in a holder; this allows
// re-submitting the existing iterator to draw the next frame, // re-submitting the existing iterator to draw the next frame,
@ -115,7 +114,7 @@ export default function Canvas({width, height, children}: CanvasProps) {
const image = painter.next().value; const image = painter.next().value;
if (image) { if (image) {
setImageHolder({ image }); setRenderImage({ image });
setAnimHolder({ painter }); setAnimHolder({ painter });
} else { } else {
setAnimHolder({ painter: null }); setAnimHolder({ painter: null });