diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index 94dd5fb..a5429e4 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -17,7 +17,7 @@ import { Close, Erase, PaintBrushAlt, RainDrop, Redo, Select_01, Undo } from "carbon-icons-svelte" import StackPreview from './sections/StackPreview.svelte' import type { Canvas } from './types/canvas' - import { BrushTool, EraserTool, type Tool } from './types/tools'; + import { BrushTool, EraserTool, FillTool, type Tool } from './types/tools'; let theme: 'white'|'g10'|'g80'|'g90'|'g100' = 'g90' @@ -34,6 +34,7 @@ let showPreview: boolean = false // let toolSelect = new SelectTool() + let toolFill = new FillTool() let toolErase = new EraserTool() let toolBrush = new BrushTool() let currentTool: Tool = toolBrush @@ -99,7 +100,7 @@
diff --git a/frontend/src/sections/Editor2D.svelte b/frontend/src/sections/Editor2D.svelte index 357d3a6..ab65131 100644 --- a/frontend/src/sections/Editor2D.svelte +++ b/frontend/src/sections/Editor2D.svelte @@ -4,7 +4,7 @@ import type { data } from '../../wailsjs/go/models.ts' import type { LoadedFile } from '../types/file' import type { PixelPosition } from '../types/shapes' - import { BrushTool, EraserTool, type Tool } from '../types/tools' + import { BrushTool, EraserTool, FillTool, type Tool } from '../types/tools' export let file: LoadedFile export let animation: data.Animation @@ -189,6 +189,10 @@ currentTool.pointerDown({file, brushSize: 3, colorIndex: primaryColorIndex}, {x: mousePixelX, y: mousePixelY, id: e.button }) } else if (currentTool instanceof EraserTool) { currentTool.pointerDown({file, brushSize: 3}, {x: mousePixelX, y: mousePixelY, id: e.button }) + } else if (currentTool instanceof FillTool) { + currentTool.pointerDown({file, colorIndex: primaryColorIndex}, {x: mousePixelX, y: mousePixelY, id: e.button }) + } else { + currentTool.pointerDown({file}, {x: mousePixelX, y: mousePixelY, id: e.button }) } } }) @@ -252,6 +256,10 @@ currentTool.pointerMove({file, brushSize: 3, colorIndex: primaryColorIndex}, {x: mousePixelX, y: mousePixelY, id: 0 }) } else if (currentTool instanceof EraserTool) { currentTool.pointerMove({file, brushSize: 3}, {x: mousePixelX, y: mousePixelY, id: 0 }) + } else if (currentTool instanceof FillTool) { + currentTool.pointerMove({file, colorIndex: primaryColorIndex}, {x: mousePixelX, y: mousePixelY, id: 0 }) + } else { + currentTool.pointerMove({file}, {x: mousePixelX, y: mousePixelY, id: 0 }) } } } diff --git a/frontend/src/types/tools.ts b/frontend/src/types/tools.ts index 60411ce..c5b782c 100644 --- a/frontend/src/types/tools.ts +++ b/frontend/src/types/tools.ts @@ -1,5 +1,5 @@ import { PixelPlaceUndoable, type LoadedFile, PixelsPlaceUndoable } from "./file" -import { FilledCircle } from "./shapes" +import { FilledCircle, type PixelPosition } from "./shapes" export interface ToolContext { file: LoadedFile @@ -27,6 +27,10 @@ export interface EraserToolContext { brushSize: number } +export interface FloodToolContext { + colorIndex: number +} + export class BrushTool implements Tool { private active: boolean isActive(): boolean { @@ -88,4 +92,47 @@ export class EraserTool extends BrushTool { pointerMove(ctx: ToolContext & EraserToolContext, ptr: Pointer) { super.pointerMove({...ctx, colorIndex: 0}, ptr) } +} + +export class FillTool implements Tool { + private active: boolean + isActive(): boolean { + return this.active + } + + private pixels: PixelPosition[] = [] + + pointerDown(ctx: ToolContext & FloodToolContext, ptr: Pointer) { + this.active = true + this.pixels = [] + + let traversed = new Set