From d49b68ae2958160d54f060bf35420040c89144f3 Mon Sep 17 00:00:00 2001 From: Victor Seiji Hariki Date: Sun, 4 Dec 2022 19:35:44 -0300 Subject: [PATCH] add options to brushes for opacity, and mask blur Signed-off-by: Victor Seiji Hariki --- js/ui/tool/colorbrush.js | 27 +++++++++++++++++++-- js/ui/tool/maskbrush.js | 52 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/js/ui/tool/colorbrush.js b/js/ui/tool/colorbrush.js index 738c6ae..c460534 100644 --- a/js/ui/tool/colorbrush.js +++ b/js/ui/tool/colorbrush.js @@ -3,7 +3,12 @@ const _color_brush_draw_callback = (evn, state) => { ctx.strokeStyle = state.color; - ctx.filter = "blur(" + state.brushBlur + "px)"; + ctx.filter = + "blur(" + + state.brushBlur + + "px) opacity(" + + state.brushOpacity * 100 + + "%)"; ctx.lineWidth = state.brushSize; ctx.beginPath(); ctx.moveTo( @@ -13,6 +18,7 @@ const _color_brush_draw_callback = (evn, state) => { ctx.lineTo(evn.x, evn.y); ctx.lineJoin = ctx.lineCap = "round"; ctx.stroke(); + ctx.filter = null; }; const _color_brush_erase_callback = (evn, state, ctx) => { @@ -130,6 +136,7 @@ const colorBrushTool = () => state.color = "#FFFFFF"; state.brushSize = 32; state.brushBlur = 0; + state.brushOpacity = 1; state.affectMask = true; state.setBrushSize = (size) => { state.brushSize = size; @@ -327,6 +334,7 @@ const colorBrushTool = () => const cropped = cropCanvas(canvas, {border: 10}); const bb = cropped.bb; + uil.ctx.filter = null; uil.ctx.clearRect(0, 0, uil.canvas.width, uil.canvas.height); uil.ctx.drawImage(bkpcanvas, 0, 0); @@ -366,7 +374,21 @@ const colorBrushTool = () => state.ctxmenu.brushSizeSlider = brushSizeSlider.slider; state.setBrushSize = brushSizeSlider.setValue; - // Brush size slider + // Brush opacity slider + const brushOpacitySlider = _toolbar_input.slider( + state, + "brushOpacity", + "Brush Opacity", + { + min: 0, + max: 1, + step: 0.05, + textStep: 0.001, + } + ); + state.ctxmenu.brushOpacitySlider = brushOpacitySlider.slider; + + // Brush blur slider const brushBlurSlider = _toolbar_input.slider( state, "brushBlur", @@ -417,6 +439,7 @@ const colorBrushTool = () => menu.appendChild(state.ctxmenu.affectMaskCheckbox); menu.appendChild(state.ctxmenu.brushSizeSlider); + menu.appendChild(state.ctxmenu.brushOpacitySlider); menu.appendChild(state.ctxmenu.brushBlurSlider); menu.appendChild(state.ctxmenu.brushColorPicker); }, diff --git a/js/ui/tool/maskbrush.js b/js/ui/tool/maskbrush.js index dd9de32..fee3b91 100644 --- a/js/ui/tool/maskbrush.js +++ b/js/ui/tool/maskbrush.js @@ -22,10 +22,12 @@ const setMask = (state) => { } }; -const _mask_brush_draw_callback = (evn, state) => { +const _mask_brush_draw_callback = (evn, state, opacity = 100) => { maskPaintCtx.globalCompositeOperation = "source-over"; maskPaintCtx.strokeStyle = "black"; + maskPaintCtx.filter = + "blur(" + state.brushBlur + "px) opacity(" + opacity + "%)"; maskPaintCtx.lineWidth = state.brushSize; maskPaintCtx.beginPath(); maskPaintCtx.moveTo( @@ -35,12 +37,16 @@ const _mask_brush_draw_callback = (evn, state) => { maskPaintCtx.lineTo(evn.x, evn.y); maskPaintCtx.lineJoin = maskPaintCtx.lineCap = "round"; maskPaintCtx.stroke(); + maskPaintCtx.filter = null; }; -const _mask_brush_erase_callback = (evn, state) => { +const _mask_brush_erase_callback = (evn, state, opacity = 100) => { maskPaintCtx.globalCompositeOperation = "destination-out"; maskPaintCtx.strokeStyle = "black"; + maskPaintCtx.filter = "blur(" + state.brushBlur + "px)"; + maskPaintCtx.filter = + "blur(" + state.brushBlur + "px) opacity(" + opacity + "%)"; maskPaintCtx.lineWidth = state.brushSize; maskPaintCtx.beginPath(); maskPaintCtx.moveTo( @@ -50,6 +56,7 @@ const _mask_brush_erase_callback = (evn, state) => { maskPaintCtx.lineTo(evn.x, evn.y); maskPaintCtx.lineJoin = maskPaintCtx.lineCap = "round"; maskPaintCtx.stroke(); + maskPaintCtx.filter = null; }; const maskBrushTool = () => @@ -95,9 +102,13 @@ const maskBrushTool = () => brushScrollSpeed: 1 / 4, minBrushSize: 10, maxBrushSize: 500, + minBlur: 0, + maxBlur: 30, }; state.brushSize = 64; + state.brushBlur = 0; + state.brushOpacity = 1; state.setBrushSize = (size) => { state.brushSize = size; state.ctxmenu.brushSizeRange.value = size; @@ -156,12 +167,16 @@ const maskBrushTool = () => } }; - state.drawcb = (evn) => _mask_brush_draw_callback(evn, state); - state.erasecb = (evn) => _mask_brush_erase_callback(evn, state); + state.drawcb = (evn) => + _mask_brush_draw_callback(evn, state, state.brushOpacity * 100); + state.erasecb = (evn) => + _mask_brush_erase_callback(evn, state, state.brushOpacity * 100); }, populateContextMenu: (menu, state) => { if (!state.ctxmenu) { state.ctxmenu = {}; + + // Brush size slider const brushSizeSlider = _toolbar_input.slider( state, "brushSize", @@ -181,6 +196,33 @@ const maskBrushTool = () => state.ctxmenu.brushSizeSlider = brushSizeSlider.slider; state.setBrushSize = brushSizeSlider.setValue; + // Brush opacity slider + const brushOpacitySlider = _toolbar_input.slider( + state, + "brushOpacity", + "Brush Opacity", + { + min: 0, + max: 1, + step: 0.05, + textStep: 0.001, + } + ); + state.ctxmenu.brushOpacitySlider = brushOpacitySlider.slider; + + // Brush blur slider + const brushBlurSlider = _toolbar_input.slider( + state, + "brushBlur", + "Brush Blur", + { + min: state.config.minBlur, + max: state.config.maxBlur, + step: 1, + } + ); + state.ctxmenu.brushBlurSlider = brushBlurSlider.slider; + // Some mask-related action buttons const actionArray = document.createElement("div"); actionArray.classList.add("button-array"); @@ -225,6 +267,8 @@ const maskBrushTool = () => } menu.appendChild(state.ctxmenu.brushSizeSlider); + menu.appendChild(state.ctxmenu.brushOpacitySlider); + menu.appendChild(state.ctxmenu.brushBlurSlider); menu.appendChild(state.ctxmenu.actionArray); }, shortcut: "M",