Skip to content

Commit

Permalink
feat: render things on top of the overlay in the editor
Browse files Browse the repository at this point in the history
  • Loading branch information
micahg committed Jul 1, 2024
1 parent e178718 commit 7bd6d60
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ const ContentEditor = ({
return;
}

const wrkr = setupOffscreenCanvas(bg, ov);
const wrkr = setupOffscreenCanvas(bg, ov, true);
setWorker(wrkr);
internalState.transferred = true;
wrkr.onmessage = handleWorkerMessage;
Expand Down
32 changes: 21 additions & 11 deletions packages/mui/src/utils/contentworker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ let backgroundCtx: OffscreenCanvasRenderingContext2D;
let overlayCtx: OffscreenCanvasRenderingContext2D;
let fullCtx: OffscreenCanvasRenderingContext2D;
let thingCtx: OffscreenCanvasRenderingContext2D;
let imageCanvasses: CanvasImageSource[] = [];
let recording = false;
let selecting = false;
let panning = false;
Expand All @@ -36,6 +37,7 @@ const _zoom_step = 0.5;
let _max_zoom: number;
let _first_zoom_step: number;
let _frame: number;
let _things_on_top_of_overlay = false;

// canvas width and height (sent from main thread)
const _canvas: Rect = { x: 0, y: 0, width: 0, height: 0 };
Expand Down Expand Up @@ -80,7 +82,7 @@ function trimPanning() {

function renderImage(
ctx: OffscreenCanvasRenderingContext2D,
img: CanvasImageSource[] | OffscreenCanvas[],
img: CanvasImageSource[],
angle: number,
) {
// if (debug) {
Expand Down Expand Up @@ -215,15 +217,15 @@ function loadAllImages(bearer: string, background: string, overlay?: string) {

function renderVisibleCanvasses() {
renderImage(backgroundCtx, [backgroundImage], _angle);
renderImage(overlayCtx, [fullCtx.canvas, thingCtx.canvas], _angle);
renderImage(overlayCtx, imageCanvasses, _angle);
}

function renderAllCanvasses(background: ImageBitmap | null) {
if (background) {
sizeVisibleCanvasses(_canvas.width, _canvas.height);
renderImage(backgroundCtx, [background], _angle);
renderThings(thingCtx);
renderImage(overlayCtx, [thingCtx.canvas, fullCtx.canvas], _angle);
renderImage(overlayCtx, imageCanvasses, _angle);
}
}

Expand Down Expand Up @@ -292,7 +294,7 @@ function eraseBrush(x: number, y: number, radius: number, full = true) {
fullCtx.drawImage(img, 0, 0);
fullCtx.restore();
img.close();
renderImage(overlayCtx, [fullCtx.canvas, thingCtx.canvas], _angle);
renderImage(overlayCtx, imageCanvasses, _angle);
}

function renderBrush(x: number, y: number, radius: number, full = true) {
Expand All @@ -315,7 +317,7 @@ function renderBrush(x: number, y: number, radius: number, full = true) {
fullCtx.fill();
fullCtx.restore();
// dump to visible canvas
renderImage(overlayCtx, [fullCtx.canvas, thingCtx.canvas], _angle);
renderImage(overlayCtx, imageCanvasses, _angle);
}

function renderBox(
Expand All @@ -339,7 +341,7 @@ function renderBox(
fullCtx.fillStyle = style;
fullCtx.fillRect(x, y, w, h);
fullCtx.restore();
renderImage(overlayCtx, [fullCtx.canvas, thingCtx.canvas], _angle);
renderImage(overlayCtx, imageCanvasses, _angle);
}

function renderThings(ctx: OffscreenCanvasRenderingContext2D) {
Expand Down Expand Up @@ -399,15 +401,15 @@ const storeOverlay = () =>

function animateBrush(x: number, y: number) {
if (!recording) return;
renderImage(overlayCtx, [fullCtx.canvas, thingCtx.canvas], _angle);
renderImage(overlayCtx, imageCanvasses, _angle);
renderBrush(x, y, brush, false);
_frame = requestAnimationFrame(() => animateBrush(x, y));
}

function animateSelection() {
if (!recording) return;
if (selecting) {
renderImage(overlayCtx, [fullCtx.canvas, thingCtx.canvas], _angle);
renderImage(overlayCtx, imageCanvasses, _angle);
renderBox(startX, startY, endX, endY, GUIDE_FILL, false);
} else if (panning) {
// calculate the (rotated) movement since the last frame and update for the next
Expand Down Expand Up @@ -463,7 +465,7 @@ function updateThings(things?: Thing[], render = false) {
// render if we're asked (avoided in cases of subsequent full renders)
if (!render) return;
renderThings(thingCtx);
renderImage(overlayCtx, [thingCtx.canvas, fullCtx.canvas], _angle);
renderImage(overlayCtx, imageCanvasses, _angle);
}

async function update(values: TableUpdate) {
Expand Down Expand Up @@ -494,6 +496,11 @@ async function update(values: TableUpdate) {
alpha: true,
}) as OffscreenCanvasRenderingContext2D;

// set the image rendering order (in reverse, things on top => things draw last)
imageCanvasses = _things_on_top_of_overlay
? [fullCtx.canvas, thingCtx.canvas]
: [thingCtx.canvas, fullCtx.canvas];

if (ovImg) {
fullCtx.drawImage(ovImg, 0, 0);
ovImg.close();
Expand Down Expand Up @@ -539,6 +546,9 @@ self.onmessage = async (evt) => {
alpha: true,
}) as OffscreenCanvasRenderingContext2D;

// indicate if things should be rendered on top of the overlay
_things_on_top_of_overlay = !!evt.data.thingsOnTop;

break;
}
case "update": {
Expand Down Expand Up @@ -669,15 +679,15 @@ self.onmessage = async (evt) => {
case "end_erase": {
recording = false;
panning = false;
renderImage(overlayCtx, [fullCtx.canvas, thingCtx.canvas], _angle);
renderImage(overlayCtx, imageCanvasses, _angle);
storeOverlay();
break;
}
case "end_paint": {
recording = false;
panning = false;
storeOverlay();
renderImage(overlayCtx, [fullCtx.canvas, thingCtx.canvas], _angle);
renderImage(overlayCtx, imageCanvasses, _angle);
break;
}
case "end_select": {
Expand Down
2 changes: 2 additions & 0 deletions packages/mui/src/utils/offscreencanvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ let worker: Worker;
export function setupOffscreenCanvas(
backgroundCanvas: HTMLCanvasElement,
overlayCanvas: HTMLCanvasElement,
thingsOnTop = false,
): Worker {
// only create a web worker if we don't have one already
if (!worker) {
Expand All @@ -15,6 +16,7 @@ export function setupOffscreenCanvas(
worker.postMessage(
{
cmd: "init",
thingsOnTop: thingsOnTop,
background: background,
overlay: overlay,
},
Expand Down

0 comments on commit 7bd6d60

Please sign in to comment.