fix: slight performance improvements

This commit is contained in:
trafficlunar 2025-02-21 15:50:59 +00:00
parent 6773f7f87d
commit fba6ccdb80
3 changed files with 38 additions and 35 deletions

View file

@ -21,44 +21,43 @@ settings.use32bitIndex = true;
function Blocks({ blocks, missingTexture, textures, coords, scale, version, isSelectionLayer }: Props) { function Blocks({ blocks, missingTexture, textures, coords, scale, version, isSelectionLayer }: Props) {
const app = useApp(); const app = useApp();
const tilemapRef = useRef<CompositeTilemap>(); const tilemapRef = useRef<CompositeTilemap>();
const containerRef = useRef<PIXI.Container>();
const tileBlocks = () => { useEffect(() => {
if (!tilemapRef.current) return; if (!tilemapRef.current) return;
const tilemap = tilemapRef.current; const tilemap = tilemapRef.current;
tilemap.clear(); tilemap.clear();
// Tile solid colors at smaller scales // Tile solid colors at smaller scales
blocks.forEach((block) => { blocks.forEach((block) => {
tilemap.tile(textures[block.name] ?? missingTexture, block.x * 16, block.y * 16); tilemap.tile(textures[block.name] ?? missingTexture, block.x * 16, block.y * 16);
}); });
}; }, [blocks, version]);
useEffect(() => { useEffect(() => {
if (containerRef.current) return;
const container = new PIXI.Container(); const container = new PIXI.Container();
containerRef.current = container;
// Put selection layer on top of the blocks layer // Put selection layer on top of the blocks layer
app.stage.addChildAt(container, isSelectionLayer ? 1 : 0); app.stage.addChildAt(container, isSelectionLayer ? 1 : 0);
const tilemap = new CompositeTilemap(); const tilemap = new CompositeTilemap();
tilemapRef.current = tilemap; tilemapRef.current = tilemap;
if (isSelectionLayer) {
container.filters = [new PIXI.AlphaFilter(0.5)];
}
container.addChild(tilemap); container.addChild(tilemap);
tileBlocks();
}, []);
useEffect(tileBlocks, [blocks, version]); if (isSelectionLayer) container.filters = [new PIXI.AlphaFilter(0.5)];
}, []);
useEffect(() => { useEffect(() => {
if (!tilemapRef.current) return; if (!tilemapRef.current) return;
const tilemap = tilemapRef.current;
tileBlocks(); tilemap.x = coords.x;
tilemap.y = coords.y;
tilemapRef.current.x = coords.x; tilemap.scale.set(scale, scale);
tilemapRef.current.y = coords.y;
tilemapRef.current.scale.set(scale, scale);
}, [coords, scale]); }, [coords, scale]);
return null; return null;

View file

@ -53,10 +53,10 @@ function Canvas() {
const blockData = useBlockData(version); const blockData = useBlockData(version);
const stageContainerRef = useRef<HTMLDivElement>(null); const stageContainerRef = useRef<HTMLDivElement>(null);
const [mousePosition, setMousePosition] = useState<Position>({ x: 0, y: 0 }); const mousePosition = useRef<Position>({ x: 0, y: 0 });
const [mouseCoords, setMouseCoords] = useState<Position>({ x: 0, y: 0 }); const [mouseCoords, setMouseCoords] = useState<Position>({ x: 0, y: 0 });
const mouseMovementRef = useRef<Position>({ x: 0, y: 0 }); const mouseMovementRef = useRef<Position>({ x: 0, y: 0 });
const [dragging, setDragging] = useState(false); const dragging = useRef(false);
const dragStartCoordsRef = useRef<Position>({ x: 0, y: 0 }); const dragStartCoordsRef = useRef<Position>({ x: 0, y: 0 });
const holdingShiftRef = useRef(false); const holdingShiftRef = useRef(false);
@ -78,7 +78,7 @@ function Canvas() {
const paintBucketTool = usePaintBucketTool(mouseCoords); const paintBucketTool = usePaintBucketTool(mouseCoords);
const shapeTool = useShapeTool(mouseCoords, dragStartCoordsRef.current, holdingShiftRef.current); const shapeTool = useShapeTool(mouseCoords, dragStartCoordsRef.current, holdingShiftRef.current);
const eyedropperTool = useEyedropperTool(mouseCoords); const eyedropperTool = useEyedropperTool(mouseCoords);
const zoomTool = useZoomTool(mousePosition, holdingAltRef.current); const zoomTool = useZoomTool(mousePosition.current, holdingAltRef.current);
const visibleArea = useMemo(() => { const visibleArea = useMemo(() => {
const blockSize = 16 * scale; const blockSize = 16 * scale;
@ -105,7 +105,7 @@ function Canvas() {
const updateCssCursor = useCallback(() => { const updateCssCursor = useCallback(() => {
const cursorMapping: Partial<Record<Tool, string>> = { const cursorMapping: Partial<Record<Tool, string>> = {
hand: dragging ? "grab" : "grabbing", hand: dragging.current ? "grabbing" : "grab",
move: "move", move: "move",
zoom: holdingAltRef.current ? "zoom-out" : "zoom-in", zoom: holdingAltRef.current ? "zoom-out" : "zoom-in",
}; };
@ -132,7 +132,7 @@ function Canvas() {
tools[tool]?.use(); tools[tool]?.use();
}, [tool, selectedBlock, moveTool, rectangleSelectTool, lassoTool, pencilTool, eraserTool, shapeTool]); }, [tool, selectedBlock, moveTool, rectangleSelectTool, lassoTool, pencilTool, eraserTool, shapeTool]);
const onMouseMove = useCallback( const onPointerMove = useCallback(
(e: React.MouseEvent) => { (e: React.MouseEvent) => {
if (!stageContainerRef.current) return; if (!stageContainerRef.current) return;
const oldMouseCoords = mouseCoords; const oldMouseCoords = mouseCoords;
@ -146,18 +146,20 @@ function Canvas() {
y: Math.floor((mouseY - coords.y) / (16 * scale)), y: Math.floor((mouseY - coords.y) / (16 * scale)),
}; };
setMousePosition({ mousePosition.current = {
x: mouseX, x: mouseX,
y: mouseY, y: mouseY,
}); };
setMouseCoords(newMouseCoords); if (newMouseCoords.x !== mouseCoords.x || newMouseCoords.y !== mouseCoords.y) {
setMouseCoords(newMouseCoords);
}
mouseMovementRef.current = { mouseMovementRef.current = {
x: newMouseCoords.x - oldMouseCoords.x, x: newMouseCoords.x - oldMouseCoords.x,
y: newMouseCoords.y - oldMouseCoords.y, y: newMouseCoords.y - oldMouseCoords.y,
}; };
if (dragging) { if (dragging.current) {
if (tool === "hand") { if (tool === "hand") {
setCoords((prevCoords) => ({ setCoords((prevCoords) => ({
x: prevCoords.x + e.movementX, x: prevCoords.x + e.movementX,
@ -172,7 +174,8 @@ function Canvas() {
); );
const onMouseDown = useCallback(() => { const onMouseDown = useCallback(() => {
setDragging(true); dragging.current = true;
onToolUse(); onToolUse();
updateCssCursor(); updateCssCursor();
@ -185,7 +188,8 @@ function Canvas() {
}, [onToolUse, updateCssCursor, mouseCoords, blocks, selectionCoords, tool, setSelectionCoords]); }, [onToolUse, updateCssCursor, mouseCoords, blocks, selectionCoords, tool, setSelectionCoords]);
const onMouseUp = useCallback(() => { const onMouseUp = useCallback(() => {
setDragging(false); dragging.current = false;
updateCssCursor(); updateCssCursor();
pencilTool.stop(); pencilTool.stop();
@ -203,7 +207,7 @@ function Canvas() {
); );
} }
if (tool === "rectangle-select" || tool === "magic-wand" || tool === "lasso") { if (["rectangle-select", "magic-wand", "lasso"].includes(tool)) {
// startSelectionCoordsRef will mutate if we pass it directly // startSelectionCoordsRef will mutate if we pass it directly
const prevSelection = [...startSelectionCoordsRef.current]; const prevSelection = [...startSelectionCoordsRef.current];
@ -223,8 +227,8 @@ function Canvas() {
setScale(newScale); setScale(newScale);
setCoords({ setCoords({
x: mousePosition.x - ((mousePosition.x - coords.x) / scale) * newScale, x: mousePosition.current.x - ((mousePosition.current.x - coords.x) / scale) * newScale,
y: mousePosition.y - ((mousePosition.y - coords.y) / scale) * newScale, y: mousePosition.current.y - ((mousePosition.current.y - coords.y) / scale) * newScale,
}); });
}, },
[scale, setScale, setCoords, mousePosition, coords] [scale, setScale, setCoords, mousePosition, coords]
@ -263,7 +267,7 @@ function Canvas() {
break; break;
} }
case " ": // Space case " ": // Space
setDragging(true); dragging.current = true;
oldToolRef.current = tool; oldToolRef.current = tool;
setTool("hand"); setTool("hand");
setCssCursor("grabbing"); setCssCursor("grabbing");
@ -390,7 +394,7 @@ function Canvas() {
(e: React.KeyboardEvent) => { (e: React.KeyboardEvent) => {
switch (e.key) { switch (e.key) {
case " ": // Space case " ": // Space
setDragging(false); dragging.current = false;
setCssCursor("grab"); setCssCursor("grab");
if (!oldToolRef.current) return; if (!oldToolRef.current) return;
@ -455,8 +459,8 @@ function Canvas() {
onPinch: ({ offset: [d] }) => { onPinch: ({ offset: [d] }) => {
setScale(d); setScale(d);
setCoords({ setCoords({
x: mousePosition.x - ((mousePosition.x - coords.x) / scale) * d, x: mousePosition.current.x - ((mousePosition.current.x - coords.x) / scale) * d,
y: mousePosition.y - ((mousePosition.y - coords.y) / scale) * d, y: mousePosition.current.y - ((mousePosition.current.y - coords.y) / scale) * d,
}); });
}, },
}, },
@ -477,7 +481,7 @@ function Canvas() {
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
onKeyUp={onKeyUp} onKeyUp={onKeyUp}
onPointerDown={onMouseDown} onPointerDown={onMouseDown}
onPointerMove={onMouseMove} onPointerMove={onPointerMove}
onPointerUp={onMouseUp} onPointerUp={onMouseUp}
onWheel={onWheel} onWheel={onWheel}
options={{ backgroundAlpha: 0 }} options={{ backgroundAlpha: 0 }}

View file

@ -28,7 +28,7 @@ export function useEraserTool(mouseCoords: Position) {
} }
}; };
// Interpolate to ensure continuous erasing // Interpolate to remove holes
if (lastPosition.current) { if (lastPosition.current) {
const interpolatedPositions = interpolate(radius, lastPosition.current, radiusPosition); const interpolatedPositions = interpolate(radius, lastPosition.current, radiusPosition);
if (!interpolatedPositions) return; if (!interpolatedPositions) return;