79 lines
2.5 KiB
JavaScript
79 lines
2.5 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});
|
|
}
|
|
|
|
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 = '#ff00ff'; // Magenta
|
|
this.ctx.fillRect(pos.x, pos.y, half, half);
|
|
this.ctx.fillRect(pos.x + half, pos.y + half, half, half);
|
|
this.ctx.fillStyle = '#000000'; // Black
|
|
this.ctx.fillRect(pos.x + half, pos.y, half, half);
|
|
this.ctx.fillRect(pos.x, pos.y + half, half, half);
|
|
};
|
|
|
|
if (id === ':missing') {
|
|
drawMissing();
|
|
return this.uvmap.get(id);
|
|
}
|
|
|
|
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';
|
|
});
|
|
this.ctx.drawImage(img, pos.x, pos.y, this.cellSize, this.cellSize);
|
|
} catch (e) {
|
|
console.warn(`Missing texture: ${id}`);
|
|
drawMissing();
|
|
}
|
|
|
|
return this.uvmap.get(id);
|
|
}
|
|
} |