blockmatic/src/components/canvas/Blocks.tsx

66 lines
1.6 KiB
TypeScript

/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect, useRef } from "react";
import * as PIXI from "pixi.js";
import { useApp } from "@pixi/react";
import { CompositeTilemap, settings } from "@pixi/tilemap";
interface Props {
blocks: Block[];
missingTexture: PIXI.Texture | undefined;
textures: Record<string, PIXI.Texture>;
solidTextures: Record<string, PIXI.Texture>;
coords: Position;
scale: number;
version: number;
}
// Lifts 16,000 tiles limit
settings.use32bitIndex = true;
function Blocks({ blocks, missingTexture, textures, solidTextures, coords, scale, version }: Props) {
const app = useApp();
const tilemapRef = useRef<CompositeTilemap>();
const tileBlocks = () => {
if (!tilemapRef.current) return;
const tilemap = tilemapRef.current;
tilemap.clear();
// Tile solid colors at smaller scales
if (scale >= 0.4) {
blocks.forEach((block) => {
tilemap.tile(textures[block.name] ?? missingTexture, block.x * 16, block.y * 16);
});
} else {
blocks.forEach((block) => {
tilemap.tile(solidTextures[`${block.name}`] ?? missingTexture, block.x * 16, block.y * 16);
});
}
};
useEffect(() => {
const tilemap = new CompositeTilemap();
tilemapRef.current = tilemap;
tilemap.cullable = true;
app.stage.addChildAt(tilemap, 0);
tileBlocks();
}, []);
useEffect(tileBlocks, [blocks, version]);
useEffect(() => {
if (!tilemapRef.current) return;
tileBlocks();
tilemapRef.current.x = coords.x;
tilemapRef.current.y = coords.y;
tilemapRef.current.scale.set(scale, scale);
}, [coords, scale]);
return null;
}
export default Blocks;