| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| import { state } from '../state.js'; |
| import { canvasCoords } from '../canvas-coords.js'; |
|
|
| const STROKE_TOOLS = new Set(['brush', 'eraser', 'inpaint']); |
|
|
| function strokeLabel(tool) { |
| if (tool === 'brush') return 'Brush stroke'; |
| if (tool === 'eraser') return 'Eraser stroke'; |
| if (tool === 'inpaint') return state.inpaintEraseStroke ? 'Erase mask' : 'Paint mask'; |
| return 'Stroke'; |
| } |
|
|
| export function createStrokeTool({ |
| saveState, strokeTo, composite, |
| getActiveMaskLayer, activeParentLayer, ensureActiveMaskLayer, createLayer, |
| renderLayerPanel, syncToolClearIndicators, |
| }) { |
| return { |
| |
| |
| |
| |
| tryBegin(e) { |
| if (!STROKE_TOOLS.has(state.tool)) return false; |
| |
| |
| |
| if (state.tool === 'inpaint') { |
| const flip = e && e.ctrlKey && e.altKey; |
| state.inpaintEraseStroke = flip ? !state.inpaintEraseMode : state.inpaintEraseMode; |
| |
| |
| |
| if (!getActiveMaskLayer()) { |
| let parent = activeParentLayer(); |
| if (!parent) { |
| parent = createLayer('Layer 1', state.imgWidth, state.imgHeight); |
| state.layers.push(parent); |
| state.activeLayerId = parent.id; |
| } |
| if (parent.masks && parent.masks.length) { |
| parent.activeMaskId = parent.masks[parent.masks.length - 1].id; |
| const m = getActiveMaskLayer(); |
| if (m) { |
| state.maskCanvas = m.canvas; |
| state.maskCtx = m.ctx; |
| renderLayerPanel(); |
| } |
| } else { |
| const mk = ensureActiveMaskLayer(); |
| if (mk) { |
| state.maskCanvas = mk.canvas; |
| state.maskCtx = mk.ctx; |
| renderLayerPanel(); |
| } |
| } |
| } |
| } |
| saveState(strokeLabel(state.tool)); |
| state.drawing = true; |
| const coords = canvasCoords(e, state.mainCanvas); |
| state.lastX = coords.x; |
| state.lastY = coords.y; |
| strokeTo(coords.x, coords.y); |
| return true; |
| }, |
|
|
| |
| |
| |
| |
| tryContinue(e) { |
| if (!state.drawing) return false; |
| e.preventDefault(); |
| const coords = canvasCoords(e, state.mainCanvas); |
| strokeTo(coords.x, coords.y); |
| return true; |
| }, |
|
|
| |
| |
| |
| tryEnd() { |
| if (!state.drawing) return false; |
| const wasDrawingInpaint = state.tool === 'inpaint'; |
| state.drawing = false; |
| composite(); |
| if (wasDrawingInpaint) syncToolClearIndicators(); |
| return true; |
| }, |
| }; |
| } |
|
|