mirror of
https://github.com/trafficlunar/blockmatic.git
synced 2026-06-28 06:34:13 +00:00
fix: holes in pencil tool
This commit is contained in:
parent
7233452877
commit
214fed6e94
3 changed files with 60 additions and 18 deletions
|
|
@ -1,10 +1,11 @@
|
|||
import { useContext } from "react";
|
||||
import { useContext, useRef } from "react";
|
||||
|
||||
import { CanvasContext } from "@/context/Canvas";
|
||||
import { SelectionContext } from "@/context/Selection";
|
||||
import { ToolContext } from "@/context/Tool";
|
||||
|
||||
import { useRadiusPosition } from "../useRadiusPosition";
|
||||
import { useRadiusPosition } from "@/hooks/useRadiusPosition";
|
||||
import { interpolate } from "@/utils/interpolate";
|
||||
|
||||
export function usePencilTool(mouseCoords: Position) {
|
||||
const { blocks, setBlocks } = useContext(CanvasContext);
|
||||
|
|
@ -12,33 +13,52 @@ export function usePencilTool(mouseCoords: Position) {
|
|||
const { selectedBlock, radius } = useContext(ToolContext);
|
||||
|
||||
const radiusPosition = useRadiusPosition(mouseCoords);
|
||||
const lastPosition = useRef<Position | null>(null);
|
||||
|
||||
const stop = () => {
|
||||
lastPosition.current = null;
|
||||
};
|
||||
|
||||
const use = () => {
|
||||
// Don't allow the user to add air blocks
|
||||
if (selectedBlock == "air") return;
|
||||
const radiusBlocks: Block[] = [];
|
||||
const newBlocks: Block[] = [];
|
||||
|
||||
for (let x = 0; x < radius; x++) {
|
||||
for (let y = 0; y < radius; y++) {
|
||||
const tileX = radiusPosition.x + x;
|
||||
const tileY = radiusPosition.y + y;
|
||||
const addBlock = (x: number, y: number) => {
|
||||
if (isInSelection(x, y)) {
|
||||
newBlocks.push({
|
||||
name: selectedBlock,
|
||||
x,
|
||||
y,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Only add blocks within the selection
|
||||
if (isInSelection(tileX, tileY)) {
|
||||
radiusBlocks.push({
|
||||
name: selectedBlock,
|
||||
x: tileX,
|
||||
y: tileY,
|
||||
});
|
||||
// Interpolate to remove holes
|
||||
if (lastPosition.current) {
|
||||
const interpolatedPositions = interpolate(radius, lastPosition.current, radiusPosition);
|
||||
if (!interpolatedPositions) return;
|
||||
|
||||
interpolatedPositions.forEach(({ x, y }) => addBlock(x, y));
|
||||
} else {
|
||||
for (let x = 0; x < radius; x++) {
|
||||
for (let y = 0; y < radius; y++) {
|
||||
const tileX = radiusPosition.x + x;
|
||||
const tileY = radiusPosition.y + y;
|
||||
|
||||
addBlock(tileX, tileY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove duplicates
|
||||
const mergedBlocks = blocks.filter((block) => {
|
||||
return !radiusBlocks.some((newBlock) => block.x === newBlock.x && block.y === newBlock.y);
|
||||
return !newBlocks.some((b) => block.x === b.x && block.y === b.y);
|
||||
});
|
||||
|
||||
setBlocks([...mergedBlocks, ...radiusBlocks]);
|
||||
setBlocks([...mergedBlocks, ...newBlocks]);
|
||||
lastPosition.current = radiusPosition;
|
||||
};
|
||||
|
||||
return { use };
|
||||
return { stop, use };
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue