import { listen } from "rkgk/framework.js"; function numChunksInRectangle(rect, chunkSize) { let leftChunk = Math.floor(rect.left / chunkSize); let topChunk = Math.floor(rect.top / chunkSize); let rightChunk = Math.ceil(rect.right / chunkSize); let bottomChunk = Math.ceil(rect.bottom / chunkSize); let numX = rightChunk - leftChunk; let numY = bottomChunk - topChunk; return numX * numY; } function* chunksInRectangle(rect, chunkSize) { let leftChunk = Math.floor(rect.left / chunkSize); let topChunk = Math.floor(rect.top / chunkSize); let rightChunk = Math.ceil(rect.right / chunkSize); let bottomChunk = Math.ceil(rect.bottom / chunkSize); for (let chunkY = topChunk; chunkY < bottomChunk; ++chunkY) { for (let chunkX = leftChunk; chunkX < rightChunk; ++chunkX) { yield [chunkX, chunkY]; } } } export function renderToChunksInArea(layer, renderArea, renderToPixmap) { for (let [chunkX, chunkY] of chunksInRectangle(renderArea, layer.chunkSize)) { let chunk = layer.getOrCreateChunk(chunkX, chunkY); if (chunk == null) continue; let translationX = -chunkX * layer.chunkSize; let translationY = -chunkY * layer.chunkSize; let result = renderToPixmap(chunk.pixmap, translationX, translationY); chunk.markModified(); if (result.status != "ok") return result; } return { status: "ok" }; } export function dotterRenderArea(wall, dotter) { let halfPaintArea = wall.paintArea / 2; return { left: dotter.toX - halfPaintArea, top: dotter.toY - halfPaintArea, right: dotter.toX + halfPaintArea, bottom: dotter.toY + halfPaintArea, }; } export function selfController(interactionQueue, wall, layer, event) { let renderArea = null; return { async runScribble(renderToPixmap) { interactionQueue.push({ kind: "scribble" }); if (renderArea != null) { let numChunksToRender = numChunksInRectangle(renderArea, layer.chunkSize); let result = renderToChunksInArea(layer, renderArea, renderToPixmap); if (!layer.canFitNewChunks(numChunksToRender)) { console.debug("too many chunks rendered; committing interaction early"); event.earlyCommitInteraction(); } return result; } else { console.debug("render area is empty, nothing will be rendered"); } return { status: "ok" }; }, async runDotter() { let dotter = await event.continueAsDotter(); interactionQueue.push({ kind: "dotter", from: { x: dotter.fromX, y: dotter.fromY }, to: { x: dotter.toX, y: dotter.toY }, num: dotter.num, }); renderArea = dotterRenderArea(wall, dotter); return dotter; }, }; }