add renderer for small-pixels overlay

This commit is contained in:
HF 2024-02-04 18:51:52 +01:00
parent 7a15fa556b
commit 47b4db2602
4 changed files with 99 additions and 8 deletions

View File

@ -23,6 +23,7 @@ import {
renderPlaceholder,
renderPotatoPlaceholder,
renderOverlay,
renderSmallPOverlay,
} from './render2Delements';
import PixelPainterControls from '../controls/PixelPainterControls';
@ -273,7 +274,6 @@ class Renderer2D extends Renderer {
const [x, y] = getPixelFromChunkOffset(i, j, offset, canvasSize);
// TODO centerChunk is scaled!
const [canX, canY] = this.centerChunk
.map((z) => (z + 0.5) * TILE_SIZE - canvasSize / 2);
const { width: canvasWidth, height: canvasHeight } = this.canvas;
@ -423,10 +423,12 @@ class Renderer2D extends Renderer {
}
context.restore();
// TODO conditions
renderOverlay(
this.canvas, chunkPosition, canvasSize, scale,
this.tiledScale, this.scaleThreshold,
);
if (false) {
renderOverlay(
state, this.canvas, chunkPosition, scale,
this.tiledScale, this.scaleThreshold,
);
}
}
@ -552,6 +554,11 @@ class Renderer2D extends Renderer {
);
}
// TODO conditions
if (viewscale >= 5) {
renderSmallPOverlay(viewport, _view, viewscale);
}
if (showGrid && viewscale >= 8) {
renderGrid(state, viewport, _view, viewscale, isLightGrid);
}

View File

@ -19,11 +19,46 @@ class Template {
height;
// if image is loaded
ready = false;
// small pixels image
#imageSmall;
constructor(imageId) {
this.id = imageId;
}
get imageSmall() {
if (!this.#imageSmall) {
const imgData = this.image.getContext('2d').getImageData(
0, 0, this.width, this.height,
);
const imageSmall = document.createElement('canvas');
imageSmall.width = this.width * 3;
imageSmall.height = this.height * 3;
const targetContext = imageSmall.getContext('2d');
const targetData = targetContext.getImageData(
0, 0, imageSmall.width, imageSmall.height,
);
let c = 0;
let o = targetData.width * 4 + 4;
while (c < imgData.data.length) {
for (let r = 0; r < imgData.width; r += 1) {
targetData.data[o] = imgData.data[c];
targetData.data[++o] = imgData.data[++c];
targetData.data[++o] = imgData.data[++c];
targetData.data[++o] = imgData.data[++c];
o += 1 + 2 * 4;
c += 1;
}
o += targetData.width * 4 * 2;
}
targetContext.putImageData(targetData, 0, 0);
this.#imageSmall = imageSmall;
}
return this.#imageSmall;
}
async arrayBuffer() {
return canvasToBuffer(this.image);
}

View File

@ -52,8 +52,7 @@ export function renderPotatoPlaceholder(
) {
const viewportCtx = $viewport.getContext('2d');
const { hover } = state.canvas;
const { palette, selectedColor } = state.canvas;
const { palette, selectedColor, hover } = state.canvas;
const [sx, sy] = worldToScreen(view, scale, $viewport, hover);
@ -107,13 +106,14 @@ export function renderGrid(
* Overlay draws onto offscreen canvas, so its doing weirder math
*/
export function renderOverlay(
state,
$canvas,
centerChunk,
canvasSize,
scale,
tiledScale,
scaleThreshold,
) {
const { canvasSize } = state.canvas;
// world coordinates of center of center chunk
const [x, y] = centerChunk
.map((z) => z * TILE_SIZE / tiledScale
@ -138,6 +138,7 @@ export function renderOverlay(
for (const template of templates) {
const image = templateLoader.getTemplateSync(template.imageId);
if (!image) continue;
context.drawImage(image,
template.x - x + width / 2 / offscreenScale,
template.y - y + height / 2 / offscreenScale,
@ -145,3 +146,38 @@ export function renderOverlay(
}
context.restore();
}
/*
* Small pixel overlay draws into viewport, because it needs
* high scale values
*/
export function renderSmallPOverlay(
$viewport,
view,
scale,
) {
const [x, y] = view;
const { width, height } = $viewport;
const horizontalRadius = width / 2 / scale;
const verticalRadius = height / 2 / scale;
const templates = templateLoader.getTemplatesInView(
x, y, horizontalRadius, verticalRadius,
);
if (!templates.length) return;
const context = $viewport.getContext('2d');
if (!context) return;
const relScale = scale / 3;
context.save();
context.scale(relScale, relScale);
for (const template of templates) {
const image = templateLoader.getSmallTemplateSync(template.imageId);
if (!image) continue;
context.drawImage(image,
(template.x - x) * 3 + width / 2 / relScale,
(template.y - y) * 3 + height / 2 / relScale,
);
}
context.restore();
}

View File

@ -63,6 +63,19 @@ class TemplateLoader {
return null;
}
getSmallTemplateSync(id) {
if (!this.ready) {
return null;
}
const template = this.#templates.get(id);
if (template) {
return template.imageSmall;
}
// TODO some store action when available
this.loadExistingTemplate(id);
return null;
}
getTemplatesInView(x, y, horizontalRadius, verticalRadius) {
const topX = x - horizontalRadius;
const topY = y - verticalRadius;