47 lines
1.7 KiB
JavaScript
47 lines
1.7 KiB
JavaScript
/**
|
|
* Magic-wand tool — single-click flood-fill selection on the active
|
|
* layer's pixels. Shift/Alt modifiers override the persistent mode
|
|
* toggle for the duration of the click (add / subtract).
|
|
*
|
|
* Clicking inside an existing selection with no modifier deselects.
|
|
*
|
|
* Wand is selection-only — it doesn't mutate the layer until the user
|
|
* invokes an action (Erase / Copy / etc.) from the panel. That's why
|
|
* it has just a `click` handler instead of begin/drag/end.
|
|
*
|
|
* @param {{
|
|
* activeLayer: () => object | null,
|
|
* saveState: () => void,
|
|
* composite: () => void,
|
|
* wandHits: (cx: number, cy: number) => boolean,
|
|
* runMagicWand: (cx: number, cy: number, mode: 'replace'|'add'|'subtract') => void,
|
|
* }} deps
|
|
*/
|
|
import { state } from '../state.js';
|
|
import { canvasCoords } from '../canvas-coords.js';
|
|
|
|
export function createWandTool({ activeLayer, saveState, composite, wandHits, runMagicWand }) {
|
|
return {
|
|
click(e) {
|
|
const layer = activeLayer();
|
|
if (!layer) return;
|
|
const coords = canvasCoords(e, state.mainCanvas);
|
|
// Persistent toggle sets the default mode; Shift forces add, Alt
|
|
// forces subtract regardless of the toggle (modifiers always win).
|
|
let mode = state.wandMode || 'replace';
|
|
if (e.shiftKey) mode = 'add';
|
|
else if (e.altKey) mode = 'subtract';
|
|
// Click INSIDE the existing selection with no modifier → deselect.
|
|
if (mode === 'replace' && wandHits(coords.x, coords.y)) {
|
|
saveState();
|
|
state.wandMask = null;
|
|
state.wandLayerId = null;
|
|
state.wandLastSeed = null;
|
|
composite();
|
|
return;
|
|
}
|
|
runMagicWand(coords.x, coords.y, mode);
|
|
},
|
|
};
|
|
}
|