From 0cb18092ee40ba2fb4a53e67b1906cc96c23c542 Mon Sep 17 00:00:00 2001 From: trafficlunar Date: Sun, 19 Jan 2025 13:22:54 +0000 Subject: [PATCH] feat: magic wand tool --- src/components/canvas/Canvas.tsx | 46 +++++++++++++++++++++++++++++--- src/components/toolbar/index.tsx | 22 +++++++++++---- src/types.d.ts | 2 +- 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/components/canvas/Canvas.tsx b/src/components/canvas/Canvas.tsx index 3431356..4e44862 100644 --- a/src/components/canvas/Canvas.tsx +++ b/src/components/canvas/Canvas.tsx @@ -301,6 +301,43 @@ function Canvas() { const onClick = useCallback(() => { switch (tool) { + case "magic-wand": { + const visited = new Set(); + const result: CoordinateArray = []; + const startBlock = blocks.find((block) => block.x === mouseCoords.x && block.y === mouseCoords.y); + + // Return if the block is not found + if (!startBlock) return result; + + function depthFirstSearch(block: Block) { + const key = `${block.x},${block.y}`; + if (visited.has(key)) return; + visited.add(key); + result.push([block.x, block.y]); + + // Directions for adjacent blocks (up, down, left, right) + const directions = [ + { dx: 0, dy: 1 }, + { dx: 0, dy: -1 }, + { dx: 1, dy: 0 }, + { dx: -1, dy: 0 }, + ]; + + for (const { dx, dy } of directions) { + const newX = block.x + dx; + const newY = block.y + dy; + const adjacentBlock = blocks.find((b) => b.x === newX && b.y === newY && b.name === block.name); + + if (adjacentBlock) { + depthFirstSearch({ ...block, x: newX, y: newY }); + } + } + } + + depthFirstSearch({ name: startBlock.name, x: mouseCoords.x, y: mouseCoords.y }); + setSelectionCoords(result); + break; + } case "eyedropper": { const mouseBlock = blocks.find((block) => block.x === mouseCoords.x && block.y === mouseCoords.y); if (mouseBlock) setSelectedBlock(mouseBlock.name); @@ -347,15 +384,18 @@ function Canvas() { setTool("lasso"); break; case "5": - setTool("pencil"); + setTool("magic-wand"); break; case "6": - setTool("eraser"); + setTool("pencil"); break; case "7": - setTool("eyedropper"); + setTool("eraser"); break; case "8": + setTool("eyedropper"); + break; + case "9": setTool("zoom"); break; } diff --git a/src/components/toolbar/index.tsx b/src/components/toolbar/index.tsx index 3342d5f..a4acf86 100644 --- a/src/components/toolbar/index.tsx +++ b/src/components/toolbar/index.tsx @@ -1,5 +1,5 @@ import { useContext } from "react"; -import { EraserIcon, HandIcon, LassoIcon, MousePointer2Icon, PencilIcon, PipetteIcon, SquareDashedIcon, ZoomInIcon } from "lucide-react"; +import { EraserIcon, HandIcon, LassoIcon, MousePointer2Icon, PencilIcon, PipetteIcon, SquareDashedIcon, WandIcon, ZoomInIcon } from "lucide-react"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; @@ -69,6 +69,18 @@ function Toolbar() { + {/* Magic Wand */} + + + + + + + +

Magic Wand (5)

+
+
+ {/* Pencil */} @@ -77,7 +89,7 @@ function Toolbar() { -

Pencil (5)

+

Pencil (6)

@@ -89,7 +101,7 @@ function Toolbar() { -

Eraser (6)

+

Eraser (7)

@@ -101,7 +113,7 @@ function Toolbar() { -

Eyedropper (7)

+

Eyedropper (8)

@@ -113,7 +125,7 @@ function Toolbar() { -

Zoom (8)

+

Zoom (9)

diff --git a/src/types.d.ts b/src/types.d.ts index 373e790..47c3d8a 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -23,7 +23,7 @@ interface Block extends Position { type CoordinateArray = [number, number][]; -type Tool = "hand" | "move" | "rectangle-select" | "lasso" | "pencil" | "eraser" | "eyedropper" | "zoom"; +type Tool = "hand" | "move" | "rectangle-select" | "lasso" | "magic-wand" | "pencil" | "eraser" | "eyedropper" | "zoom"; interface Settings { grid: boolean;