feat(phase-8): implement comprehensive selection system with marching ants
This commit completes Phase 8 of the paint-ui implementation, adding a full
selection system with multiple selection tools, operations, and visual feedback.
**New Files:**
- types/selection.ts: Selection types, masks, and state interfaces
- lib/selection-utils.ts: Selection mask generation and manipulation algorithms
- lib/selection-operations.ts: Copy/cut/paste/delete/fill/stroke operations
- store/selection-store.ts: Selection state management with Zustand
- core/commands/selection-command.ts: Undo/redo commands for selections
- tools/rectangular-selection-tool.ts: Rectangular marquee selection
- tools/elliptical-selection-tool.ts: Elliptical marquee selection
- tools/lasso-selection-tool.ts: Free-form polygon selection
- tools/magic-wand-tool.ts: Color-based flood-fill selection
- components/selection/selection-panel.tsx: Complete selection UI panel
- components/selection/index.ts: Selection components barrel export
**Updated Files:**
- components/canvas/canvas-with-tools.tsx: Added selection tools integration and marching ants animation
- components/editor/editor-layout.tsx: Integrated SelectionPanel into layout
- store/index.ts: Added selection-store export
- store/canvas-store.ts: Renamed Selection to CanvasSelection to avoid conflicts
- tools/index.ts: Added selection tool exports
- types/index.ts: Added selection types export
- types/canvas.ts: Renamed Selection interface to CanvasSelection
**Selection Tools:**
**Marquee Tools:**
- ✨ Rectangular Selection: Click-drag rectangular regions
- ✨ Elliptical Selection: Click-drag elliptical regions
**Free-form Tools:**
- ✨ Lasso Selection: Draw free-form polygon selections
- ✨ Magic Wand: Color-based flood-fill selection with tolerance
**Selection Modes:**
- 🔷 New: Replace existing selection
- ➕ Add: Add to existing selection
- ➖ Subtract: Remove from existing selection
- ⚡ Intersect: Keep only overlapping areas
**Selection Operations:**
- 📋 Copy/Cut/Paste: Standard clipboard operations with selection mask
- 🗑️ Delete: Remove selected pixels
- 🎨 Fill Selection: Fill with current color
- 🖌️ Stroke Selection: Outline selection with current color
- 🔄 Invert Selection: Invert selected/unselected pixels
- ❌ Clear Selection: Deselect all
**Technical Features:**
- Marching ants animation (animated dashed outline at 50ms interval)
- Selection masks using Uint8Array (0-255 values for anti-aliasing)
- Feathering support (0-250px gaussian blur on selection edges)
- Tolerance control for magic wand (0-255 color difference threshold)
- Scanline polygon fill algorithm for lasso tool
- Flood-fill with Set-based visited tracking for magic wand
- Selection bounds calculation for optimized operations
- Keyboard shortcuts (Ctrl+C, Ctrl+X, Ctrl+V, Ctrl+D, Ctrl+Shift+I)
- Undo/redo integration via selection commands
- Non-destructive operations with proper history tracking
**Algorithm Implementations:**
- Rectangular mask: Simple bounds-based pixel marking
- Elliptical mask: Distance formula from ellipse center
- Lasso mask: Scanline polygon fill with edge intersection
- Magic wand: BFS flood-fill with color tolerance matching
- Mask combination: Per-pixel operations (max, subtract, AND)
- Feathering: Separable box blur (horizontal + vertical passes)
- Mask inversion: Per-pixel NOT operation with bounds recalculation
**UI/UX Features:**
- 264px wide selection panel with all tools and operations
- Tool selection with visual feedback (highlighted active tool)
- Selection mode toggles (new/add/subtract/intersect)
- Feather and tolerance sliders with live value display
- Disabled state when no selection exists
- Keyboard shortcut hints next to operations
- Visual marching ants animation (animated dashes)
Build verified: ✓ Compiled successfully in 1302ms
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 02:24:12 +01:00
|
|
|
import { create } from 'zustand';
|
|
|
|
|
import type {
|
|
|
|
|
Selection,
|
|
|
|
|
SelectionType,
|
|
|
|
|
SelectionMode,
|
|
|
|
|
SelectionState,
|
|
|
|
|
} from '@/types/selection';
|
|
|
|
|
|
|
|
|
|
interface SelectionStore extends SelectionState {
|
|
|
|
|
setActiveSelection: (selection: Selection | null) => void;
|
|
|
|
|
setSelectionType: (type: SelectionType) => void;
|
|
|
|
|
setSelectionMode: (mode: SelectionMode) => void;
|
|
|
|
|
setFeather: (feather: number) => void;
|
|
|
|
|
setTolerance: (tolerance: number) => void;
|
|
|
|
|
setMarching: (isMarching: boolean) => void;
|
|
|
|
|
clearSelection: () => void;
|
2025-11-21 17:16:06 +01:00
|
|
|
selectAll: () => void;
|
feat(phase-8): implement comprehensive selection system with marching ants
This commit completes Phase 8 of the paint-ui implementation, adding a full
selection system with multiple selection tools, operations, and visual feedback.
**New Files:**
- types/selection.ts: Selection types, masks, and state interfaces
- lib/selection-utils.ts: Selection mask generation and manipulation algorithms
- lib/selection-operations.ts: Copy/cut/paste/delete/fill/stroke operations
- store/selection-store.ts: Selection state management with Zustand
- core/commands/selection-command.ts: Undo/redo commands for selections
- tools/rectangular-selection-tool.ts: Rectangular marquee selection
- tools/elliptical-selection-tool.ts: Elliptical marquee selection
- tools/lasso-selection-tool.ts: Free-form polygon selection
- tools/magic-wand-tool.ts: Color-based flood-fill selection
- components/selection/selection-panel.tsx: Complete selection UI panel
- components/selection/index.ts: Selection components barrel export
**Updated Files:**
- components/canvas/canvas-with-tools.tsx: Added selection tools integration and marching ants animation
- components/editor/editor-layout.tsx: Integrated SelectionPanel into layout
- store/index.ts: Added selection-store export
- store/canvas-store.ts: Renamed Selection to CanvasSelection to avoid conflicts
- tools/index.ts: Added selection tool exports
- types/index.ts: Added selection types export
- types/canvas.ts: Renamed Selection interface to CanvasSelection
**Selection Tools:**
**Marquee Tools:**
- ✨ Rectangular Selection: Click-drag rectangular regions
- ✨ Elliptical Selection: Click-drag elliptical regions
**Free-form Tools:**
- ✨ Lasso Selection: Draw free-form polygon selections
- ✨ Magic Wand: Color-based flood-fill selection with tolerance
**Selection Modes:**
- 🔷 New: Replace existing selection
- ➕ Add: Add to existing selection
- ➖ Subtract: Remove from existing selection
- ⚡ Intersect: Keep only overlapping areas
**Selection Operations:**
- 📋 Copy/Cut/Paste: Standard clipboard operations with selection mask
- 🗑️ Delete: Remove selected pixels
- 🎨 Fill Selection: Fill with current color
- 🖌️ Stroke Selection: Outline selection with current color
- 🔄 Invert Selection: Invert selected/unselected pixels
- ❌ Clear Selection: Deselect all
**Technical Features:**
- Marching ants animation (animated dashed outline at 50ms interval)
- Selection masks using Uint8Array (0-255 values for anti-aliasing)
- Feathering support (0-250px gaussian blur on selection edges)
- Tolerance control for magic wand (0-255 color difference threshold)
- Scanline polygon fill algorithm for lasso tool
- Flood-fill with Set-based visited tracking for magic wand
- Selection bounds calculation for optimized operations
- Keyboard shortcuts (Ctrl+C, Ctrl+X, Ctrl+V, Ctrl+D, Ctrl+Shift+I)
- Undo/redo integration via selection commands
- Non-destructive operations with proper history tracking
**Algorithm Implementations:**
- Rectangular mask: Simple bounds-based pixel marking
- Elliptical mask: Distance formula from ellipse center
- Lasso mask: Scanline polygon fill with edge intersection
- Magic wand: BFS flood-fill with color tolerance matching
- Mask combination: Per-pixel operations (max, subtract, AND)
- Feathering: Separable box blur (horizontal + vertical passes)
- Mask inversion: Per-pixel NOT operation with bounds recalculation
**UI/UX Features:**
- 264px wide selection panel with all tools and operations
- Tool selection with visual feedback (highlighted active tool)
- Selection mode toggles (new/add/subtract/intersect)
- Feather and tolerance sliders with live value display
- Disabled state when no selection exists
- Keyboard shortcut hints next to operations
- Visual marching ants animation (animated dashes)
Build verified: ✓ Compiled successfully in 1302ms
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 02:24:12 +01:00
|
|
|
invertSelection: () => void;
|
2025-11-21 20:28:02 +01:00
|
|
|
expandSelection: (pixels: number) => void;
|
|
|
|
|
contractSelection: (pixels: number) => void;
|
|
|
|
|
featherSelection: (radius: number) => void;
|
feat(phase-8): implement comprehensive selection system with marching ants
This commit completes Phase 8 of the paint-ui implementation, adding a full
selection system with multiple selection tools, operations, and visual feedback.
**New Files:**
- types/selection.ts: Selection types, masks, and state interfaces
- lib/selection-utils.ts: Selection mask generation and manipulation algorithms
- lib/selection-operations.ts: Copy/cut/paste/delete/fill/stroke operations
- store/selection-store.ts: Selection state management with Zustand
- core/commands/selection-command.ts: Undo/redo commands for selections
- tools/rectangular-selection-tool.ts: Rectangular marquee selection
- tools/elliptical-selection-tool.ts: Elliptical marquee selection
- tools/lasso-selection-tool.ts: Free-form polygon selection
- tools/magic-wand-tool.ts: Color-based flood-fill selection
- components/selection/selection-panel.tsx: Complete selection UI panel
- components/selection/index.ts: Selection components barrel export
**Updated Files:**
- components/canvas/canvas-with-tools.tsx: Added selection tools integration and marching ants animation
- components/editor/editor-layout.tsx: Integrated SelectionPanel into layout
- store/index.ts: Added selection-store export
- store/canvas-store.ts: Renamed Selection to CanvasSelection to avoid conflicts
- tools/index.ts: Added selection tool exports
- types/index.ts: Added selection types export
- types/canvas.ts: Renamed Selection interface to CanvasSelection
**Selection Tools:**
**Marquee Tools:**
- ✨ Rectangular Selection: Click-drag rectangular regions
- ✨ Elliptical Selection: Click-drag elliptical regions
**Free-form Tools:**
- ✨ Lasso Selection: Draw free-form polygon selections
- ✨ Magic Wand: Color-based flood-fill selection with tolerance
**Selection Modes:**
- 🔷 New: Replace existing selection
- ➕ Add: Add to existing selection
- ➖ Subtract: Remove from existing selection
- ⚡ Intersect: Keep only overlapping areas
**Selection Operations:**
- 📋 Copy/Cut/Paste: Standard clipboard operations with selection mask
- 🗑️ Delete: Remove selected pixels
- 🎨 Fill Selection: Fill with current color
- 🖌️ Stroke Selection: Outline selection with current color
- 🔄 Invert Selection: Invert selected/unselected pixels
- ❌ Clear Selection: Deselect all
**Technical Features:**
- Marching ants animation (animated dashed outline at 50ms interval)
- Selection masks using Uint8Array (0-255 values for anti-aliasing)
- Feathering support (0-250px gaussian blur on selection edges)
- Tolerance control for magic wand (0-255 color difference threshold)
- Scanline polygon fill algorithm for lasso tool
- Flood-fill with Set-based visited tracking for magic wand
- Selection bounds calculation for optimized operations
- Keyboard shortcuts (Ctrl+C, Ctrl+X, Ctrl+V, Ctrl+D, Ctrl+Shift+I)
- Undo/redo integration via selection commands
- Non-destructive operations with proper history tracking
**Algorithm Implementations:**
- Rectangular mask: Simple bounds-based pixel marking
- Elliptical mask: Distance formula from ellipse center
- Lasso mask: Scanline polygon fill with edge intersection
- Magic wand: BFS flood-fill with color tolerance matching
- Mask combination: Per-pixel operations (max, subtract, AND)
- Feathering: Separable box blur (horizontal + vertical passes)
- Mask inversion: Per-pixel NOT operation with bounds recalculation
**UI/UX Features:**
- 264px wide selection panel with all tools and operations
- Tool selection with visual feedback (highlighted active tool)
- Selection mode toggles (new/add/subtract/intersect)
- Feather and tolerance sliders with live value display
- Disabled state when no selection exists
- Keyboard shortcut hints next to operations
- Visual marching ants animation (animated dashes)
Build verified: ✓ Compiled successfully in 1302ms
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 02:24:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const useSelectionStore = create<SelectionStore>((set) => ({
|
|
|
|
|
activeSelection: null,
|
|
|
|
|
selectionType: 'rectangular',
|
|
|
|
|
selectionMode: 'new',
|
|
|
|
|
feather: 0,
|
|
|
|
|
tolerance: 32,
|
|
|
|
|
isMarching: true,
|
|
|
|
|
|
|
|
|
|
setActiveSelection: (selection) =>
|
|
|
|
|
set({
|
|
|
|
|
activeSelection: selection,
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
setSelectionType: (type) =>
|
|
|
|
|
set({
|
|
|
|
|
selectionType: type,
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
setSelectionMode: (mode) =>
|
|
|
|
|
set({
|
|
|
|
|
selectionMode: mode,
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
setFeather: (feather) =>
|
|
|
|
|
set({
|
|
|
|
|
feather: Math.max(0, Math.min(250, feather)),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
setTolerance: (tolerance) =>
|
|
|
|
|
set({
|
|
|
|
|
tolerance: Math.max(0, Math.min(255, tolerance)),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
setMarching: (isMarching) =>
|
|
|
|
|
set({
|
|
|
|
|
isMarching,
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
clearSelection: () =>
|
|
|
|
|
set({
|
|
|
|
|
activeSelection: null,
|
|
|
|
|
}),
|
|
|
|
|
|
2025-11-21 17:16:06 +01:00
|
|
|
selectAll: () =>
|
|
|
|
|
set(() => {
|
|
|
|
|
const { useCanvasStore, useLayerStore } = require('@/store');
|
|
|
|
|
const { width, height } = useCanvasStore.getState();
|
|
|
|
|
const { getActiveLayer } = useLayerStore.getState();
|
|
|
|
|
const activeLayer = getActiveLayer();
|
|
|
|
|
|
|
|
|
|
if (!activeLayer) return {};
|
|
|
|
|
|
|
|
|
|
// Create a mask that covers the entire canvas
|
|
|
|
|
const maskData = new Uint8Array(width * height).fill(255);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
activeSelection: {
|
|
|
|
|
id: `selection-${Date.now()}`,
|
|
|
|
|
layerId: activeLayer.id,
|
|
|
|
|
mask: {
|
|
|
|
|
width,
|
|
|
|
|
height,
|
|
|
|
|
data: maskData,
|
|
|
|
|
bounds: {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
width,
|
|
|
|
|
height,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
inverted: false,
|
|
|
|
|
feather: 0,
|
|
|
|
|
createdAt: Date.now(),
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}),
|
|
|
|
|
|
feat(phase-8): implement comprehensive selection system with marching ants
This commit completes Phase 8 of the paint-ui implementation, adding a full
selection system with multiple selection tools, operations, and visual feedback.
**New Files:**
- types/selection.ts: Selection types, masks, and state interfaces
- lib/selection-utils.ts: Selection mask generation and manipulation algorithms
- lib/selection-operations.ts: Copy/cut/paste/delete/fill/stroke operations
- store/selection-store.ts: Selection state management with Zustand
- core/commands/selection-command.ts: Undo/redo commands for selections
- tools/rectangular-selection-tool.ts: Rectangular marquee selection
- tools/elliptical-selection-tool.ts: Elliptical marquee selection
- tools/lasso-selection-tool.ts: Free-form polygon selection
- tools/magic-wand-tool.ts: Color-based flood-fill selection
- components/selection/selection-panel.tsx: Complete selection UI panel
- components/selection/index.ts: Selection components barrel export
**Updated Files:**
- components/canvas/canvas-with-tools.tsx: Added selection tools integration and marching ants animation
- components/editor/editor-layout.tsx: Integrated SelectionPanel into layout
- store/index.ts: Added selection-store export
- store/canvas-store.ts: Renamed Selection to CanvasSelection to avoid conflicts
- tools/index.ts: Added selection tool exports
- types/index.ts: Added selection types export
- types/canvas.ts: Renamed Selection interface to CanvasSelection
**Selection Tools:**
**Marquee Tools:**
- ✨ Rectangular Selection: Click-drag rectangular regions
- ✨ Elliptical Selection: Click-drag elliptical regions
**Free-form Tools:**
- ✨ Lasso Selection: Draw free-form polygon selections
- ✨ Magic Wand: Color-based flood-fill selection with tolerance
**Selection Modes:**
- 🔷 New: Replace existing selection
- ➕ Add: Add to existing selection
- ➖ Subtract: Remove from existing selection
- ⚡ Intersect: Keep only overlapping areas
**Selection Operations:**
- 📋 Copy/Cut/Paste: Standard clipboard operations with selection mask
- 🗑️ Delete: Remove selected pixels
- 🎨 Fill Selection: Fill with current color
- 🖌️ Stroke Selection: Outline selection with current color
- 🔄 Invert Selection: Invert selected/unselected pixels
- ❌ Clear Selection: Deselect all
**Technical Features:**
- Marching ants animation (animated dashed outline at 50ms interval)
- Selection masks using Uint8Array (0-255 values for anti-aliasing)
- Feathering support (0-250px gaussian blur on selection edges)
- Tolerance control for magic wand (0-255 color difference threshold)
- Scanline polygon fill algorithm for lasso tool
- Flood-fill with Set-based visited tracking for magic wand
- Selection bounds calculation for optimized operations
- Keyboard shortcuts (Ctrl+C, Ctrl+X, Ctrl+V, Ctrl+D, Ctrl+Shift+I)
- Undo/redo integration via selection commands
- Non-destructive operations with proper history tracking
**Algorithm Implementations:**
- Rectangular mask: Simple bounds-based pixel marking
- Elliptical mask: Distance formula from ellipse center
- Lasso mask: Scanline polygon fill with edge intersection
- Magic wand: BFS flood-fill with color tolerance matching
- Mask combination: Per-pixel operations (max, subtract, AND)
- Feathering: Separable box blur (horizontal + vertical passes)
- Mask inversion: Per-pixel NOT operation with bounds recalculation
**UI/UX Features:**
- 264px wide selection panel with all tools and operations
- Tool selection with visual feedback (highlighted active tool)
- Selection mode toggles (new/add/subtract/intersect)
- Feather and tolerance sliders with live value display
- Disabled state when no selection exists
- Keyboard shortcut hints next to operations
- Visual marching ants animation (animated dashes)
Build verified: ✓ Compiled successfully in 1302ms
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 02:24:12 +01:00
|
|
|
invertSelection: () =>
|
|
|
|
|
set((state) => {
|
|
|
|
|
if (state.activeSelection) {
|
|
|
|
|
return {
|
|
|
|
|
activeSelection: {
|
|
|
|
|
...state.activeSelection,
|
|
|
|
|
inverted: !state.activeSelection.inverted,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return state;
|
|
|
|
|
}),
|
2025-11-21 20:28:02 +01:00
|
|
|
|
|
|
|
|
expandSelection: (pixels) =>
|
|
|
|
|
set((state) => {
|
|
|
|
|
if (!state.activeSelection) return state;
|
|
|
|
|
|
|
|
|
|
const { mask } = state.activeSelection;
|
|
|
|
|
const { width, height, data } = mask;
|
|
|
|
|
const newData = new Uint8Array(data.length);
|
|
|
|
|
|
|
|
|
|
// Expand selection by dilating the mask
|
|
|
|
|
for (let y = 0; y < height; y++) {
|
|
|
|
|
for (let x = 0; x < width; x++) {
|
|
|
|
|
const idx = y * width + x;
|
|
|
|
|
let maxValue = data[idx];
|
|
|
|
|
|
|
|
|
|
// Check neighbors within radius
|
|
|
|
|
for (let dy = -pixels; dy <= pixels; dy++) {
|
|
|
|
|
for (let dx = -pixels; dx <= pixels; dx++) {
|
|
|
|
|
const nx = x + dx;
|
|
|
|
|
const ny = y + dy;
|
|
|
|
|
|
|
|
|
|
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
|
|
|
|
const nidx = ny * width + nx;
|
|
|
|
|
if (data[nidx] > maxValue) {
|
|
|
|
|
maxValue = data[nidx];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newData[idx] = maxValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
activeSelection: {
|
|
|
|
|
...state.activeSelection,
|
|
|
|
|
mask: {
|
|
|
|
|
...mask,
|
|
|
|
|
data: newData,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
contractSelection: (pixels) =>
|
|
|
|
|
set((state) => {
|
|
|
|
|
if (!state.activeSelection) return state;
|
|
|
|
|
|
|
|
|
|
const { mask } = state.activeSelection;
|
|
|
|
|
const { width, height, data } = mask;
|
|
|
|
|
const newData = new Uint8Array(data.length);
|
|
|
|
|
|
|
|
|
|
// Contract selection by eroding the mask
|
|
|
|
|
for (let y = 0; y < height; y++) {
|
|
|
|
|
for (let x = 0; x < width; x++) {
|
|
|
|
|
const idx = y * width + x;
|
|
|
|
|
let minValue = data[idx];
|
|
|
|
|
|
|
|
|
|
// Check neighbors within radius
|
|
|
|
|
for (let dy = -pixels; dy <= pixels; dy++) {
|
|
|
|
|
for (let dx = -pixels; dx <= pixels; dx++) {
|
|
|
|
|
const nx = x + dx;
|
|
|
|
|
const ny = y + dy;
|
|
|
|
|
|
|
|
|
|
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
|
|
|
|
const nidx = ny * width + nx;
|
|
|
|
|
if (data[nidx] < minValue) {
|
|
|
|
|
minValue = data[nidx];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newData[idx] = minValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
activeSelection: {
|
|
|
|
|
...state.activeSelection,
|
|
|
|
|
mask: {
|
|
|
|
|
...mask,
|
|
|
|
|
data: newData,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
featherSelection: (radius) =>
|
|
|
|
|
set((state) => {
|
|
|
|
|
if (!state.activeSelection) return state;
|
|
|
|
|
|
|
|
|
|
const { mask } = state.activeSelection;
|
|
|
|
|
const { width, height, data } = mask;
|
|
|
|
|
const newData = new Uint8Array(data.length);
|
|
|
|
|
|
|
|
|
|
// Apply Gaussian blur for feathering
|
|
|
|
|
const sigma = radius / 3;
|
|
|
|
|
const kernelSize = Math.ceil(radius * 2) + 1;
|
|
|
|
|
const kernel: number[] = [];
|
|
|
|
|
let kernelSum = 0;
|
|
|
|
|
|
|
|
|
|
// Generate Gaussian kernel
|
|
|
|
|
for (let i = 0; i < kernelSize; i++) {
|
|
|
|
|
const x = i - Math.floor(kernelSize / 2);
|
|
|
|
|
const value = Math.exp(-(x * x) / (2 * sigma * sigma));
|
|
|
|
|
kernel.push(value);
|
|
|
|
|
kernelSum += value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Normalize kernel
|
|
|
|
|
for (let i = 0; i < kernel.length; i++) {
|
|
|
|
|
kernel[i] /= kernelSum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Horizontal pass
|
|
|
|
|
const temp = new Uint8Array(data.length);
|
|
|
|
|
for (let y = 0; y < height; y++) {
|
|
|
|
|
for (let x = 0; x < width; x++) {
|
|
|
|
|
let sum = 0;
|
|
|
|
|
const halfKernel = Math.floor(kernelSize / 2);
|
|
|
|
|
|
|
|
|
|
for (let k = 0; k < kernelSize; k++) {
|
|
|
|
|
const sx = x + k - halfKernel;
|
|
|
|
|
if (sx >= 0 && sx < width) {
|
|
|
|
|
sum += data[y * width + sx] * kernel[k];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
temp[y * width + x] = Math.round(sum);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Vertical pass
|
|
|
|
|
for (let y = 0; y < height; y++) {
|
|
|
|
|
for (let x = 0; x < width; x++) {
|
|
|
|
|
let sum = 0;
|
|
|
|
|
const halfKernel = Math.floor(kernelSize / 2);
|
|
|
|
|
|
|
|
|
|
for (let k = 0; k < kernelSize; k++) {
|
|
|
|
|
const sy = y + k - halfKernel;
|
|
|
|
|
if (sy >= 0 && sy < height) {
|
|
|
|
|
sum += temp[sy * width + x] * kernel[k];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newData[y * width + x] = Math.round(sum);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
activeSelection: {
|
|
|
|
|
...state.activeSelection,
|
|
|
|
|
mask: {
|
|
|
|
|
...mask,
|
|
|
|
|
data: newData,
|
|
|
|
|
},
|
|
|
|
|
feather: radius,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}),
|
feat(phase-8): implement comprehensive selection system with marching ants
This commit completes Phase 8 of the paint-ui implementation, adding a full
selection system with multiple selection tools, operations, and visual feedback.
**New Files:**
- types/selection.ts: Selection types, masks, and state interfaces
- lib/selection-utils.ts: Selection mask generation and manipulation algorithms
- lib/selection-operations.ts: Copy/cut/paste/delete/fill/stroke operations
- store/selection-store.ts: Selection state management with Zustand
- core/commands/selection-command.ts: Undo/redo commands for selections
- tools/rectangular-selection-tool.ts: Rectangular marquee selection
- tools/elliptical-selection-tool.ts: Elliptical marquee selection
- tools/lasso-selection-tool.ts: Free-form polygon selection
- tools/magic-wand-tool.ts: Color-based flood-fill selection
- components/selection/selection-panel.tsx: Complete selection UI panel
- components/selection/index.ts: Selection components barrel export
**Updated Files:**
- components/canvas/canvas-with-tools.tsx: Added selection tools integration and marching ants animation
- components/editor/editor-layout.tsx: Integrated SelectionPanel into layout
- store/index.ts: Added selection-store export
- store/canvas-store.ts: Renamed Selection to CanvasSelection to avoid conflicts
- tools/index.ts: Added selection tool exports
- types/index.ts: Added selection types export
- types/canvas.ts: Renamed Selection interface to CanvasSelection
**Selection Tools:**
**Marquee Tools:**
- ✨ Rectangular Selection: Click-drag rectangular regions
- ✨ Elliptical Selection: Click-drag elliptical regions
**Free-form Tools:**
- ✨ Lasso Selection: Draw free-form polygon selections
- ✨ Magic Wand: Color-based flood-fill selection with tolerance
**Selection Modes:**
- 🔷 New: Replace existing selection
- ➕ Add: Add to existing selection
- ➖ Subtract: Remove from existing selection
- ⚡ Intersect: Keep only overlapping areas
**Selection Operations:**
- 📋 Copy/Cut/Paste: Standard clipboard operations with selection mask
- 🗑️ Delete: Remove selected pixels
- 🎨 Fill Selection: Fill with current color
- 🖌️ Stroke Selection: Outline selection with current color
- 🔄 Invert Selection: Invert selected/unselected pixels
- ❌ Clear Selection: Deselect all
**Technical Features:**
- Marching ants animation (animated dashed outline at 50ms interval)
- Selection masks using Uint8Array (0-255 values for anti-aliasing)
- Feathering support (0-250px gaussian blur on selection edges)
- Tolerance control for magic wand (0-255 color difference threshold)
- Scanline polygon fill algorithm for lasso tool
- Flood-fill with Set-based visited tracking for magic wand
- Selection bounds calculation for optimized operations
- Keyboard shortcuts (Ctrl+C, Ctrl+X, Ctrl+V, Ctrl+D, Ctrl+Shift+I)
- Undo/redo integration via selection commands
- Non-destructive operations with proper history tracking
**Algorithm Implementations:**
- Rectangular mask: Simple bounds-based pixel marking
- Elliptical mask: Distance formula from ellipse center
- Lasso mask: Scanline polygon fill with edge intersection
- Magic wand: BFS flood-fill with color tolerance matching
- Mask combination: Per-pixel operations (max, subtract, AND)
- Feathering: Separable box blur (horizontal + vertical passes)
- Mask inversion: Per-pixel NOT operation with bounds recalculation
**UI/UX Features:**
- 264px wide selection panel with all tools and operations
- Tool selection with visual feedback (highlighted active tool)
- Selection mode toggles (new/add/subtract/intersect)
- Feather and tolerance sliders with live value display
- Disabled state when no selection exists
- Keyboard shortcut hints next to operations
- Visual marching ants animation (animated dashes)
Build verified: ✓ Compiled successfully in 1302ms
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 02:24:12 +01:00
|
|
|
}));
|