Files
wireless-docs/texture.js
David Allemang 0a32b46e93 streaming assets
2026-07-06 14:02:29 -04:00

86 lines
2.8 KiB
JavaScript

export class TextureHandler {
constructor(size) {
this.canvas = document.createElement('canvas');
this.canvas.width = size;
this.canvas.height = size;
this.ctx = this.canvas.getContext('2d', {willReadFrequently: true});
this.ctx.imageSmoothingEnabled = false;
this.uvmap = new Map();
this.pendingDraws = new Map();
this.cellSize = 16;
this.padding = 1;
this.x = 0;
this.y = 0;
this.rowHeight = 0;
}
prepare(cache, id, url) {
if (this.x + this.cellSize > this.canvas.width) {
this.x = 0;
this.y += this.rowHeight + this.padding;
this.rowHeight = 0;
}
const currentX = this.x;
const currentY = this.y;
this.x += this.cellSize + this.padding;
this.rowHeight = Math.max(this.rowHeight, this.cellSize);
const uvData = {
u: currentX / this.canvas.width,
v: currentY / this.canvas.height,
du: this.cellSize / this.canvas.width,
dv: this.cellSize / this.canvas.height,
};
this.uvmap.set(id, uvData);
this.pendingDraws.set(id, {x: currentX, y: currentY});
this.ctx.fillStyle = '#00000066';
this.ctx.fillRect(currentX, currentY, this.cellSize, this.cellSize);
}
getFallback(id) {
return this.uvmap.get(id); // UVs map to the black silhouette!
}
async process(cache, id, url) {
const pos = this.pendingDraws.get(id);
if (!pos) throw new Error(`Not prepared for ${id}.`);
this.pendingDraws.delete(id);
const drawMissing = () => {
const half = this.cellSize / 2;
this.ctx.fillStyle = '#33333366'; // Gray
this.ctx.fillRect(pos.x, pos.y, half, half);
this.ctx.fillRect(pos.x + half, pos.y + half, half, half);
this.ctx.fillStyle = '#00000066'; // Black
this.ctx.fillRect(pos.x + half, pos.y, half, half);
this.ctx.fillRect(pos.x, pos.y + half, half, half);
};
drawMissing();
if (id !== ':missing') {
try {
const img = await new Promise((resolve, reject) => {
const i = new Image();
i.crossOrigin = 'anonymous';
i.onload = () => resolve(i);
i.onerror = () => reject(new Error(`Image load failed`));
i.src = url + '.png';
});
// await new Promise(r => setTimeout(r, 2000))
this.ctx.clearRect(pos.x, pos.y, this.cellSize, this.cellSize);
this.ctx.drawImage(img, pos.x, pos.y, this.cellSize, this.cellSize);
} catch (e) {
console.warn(`Missing texture: ${id}`);
}
}
return this.uvmap.get(id);
}
}