From 6ede893585d5d44da4bf43182152dcbb61dbfc02 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Thu, 17 Aug 2017 16:50:30 -0400 Subject: [PATCH] Bring over new bug fixes from papergrapher --- src/containers/blob/blob.js | 36 ++++++++++++++++++--- src/containers/blob/broad-brush-helper.js | 2 +- src/containers/blob/segment-brush-helper.js | 17 ++++++++-- src/containers/brush-mode.jsx | 13 +++----- 4 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/containers/blob/blob.js b/src/containers/blob/blob.js index adbaedf8..c3c9c2ca 100644 --- a/src/containers/blob/blob.js +++ b/src/containers/blob/blob.js @@ -226,8 +226,37 @@ class Blobbiness { } for (let i = items.length - 1; i >= 0; i--) { + // TODO handle compound paths + if (items[i] instanceof paper.Path && (!items[i].fillColor || items[i].fillColor._alpha === 0)) { + // Gather path segments + const subpaths = []; + const firstSeg = items[i]; + const intersections = firstSeg.getIntersections(lastPath); + for (let j = intersections.length - 1; j >= 0; j--) { + const split = firstSeg.splitAt(intersections[j]); + if (split) { + split.insertAbove(firstSeg); + subpaths.push(split); + } + } + subpaths.push(firstSeg); + + // Remove the ones that are within the eraser stroke boundary + for (let k = subpaths.length - 1; k >= 0; k--) { + const segMidpoint = subpaths[k].getLocationAt(subpaths[k].length / 2).point; + if (lastPath.contains(segMidpoint)) { + subpaths[k].remove(); + subpaths.splice(k, 1); + } + } + lastPath.remove(); + // TODO add back undo + // pg.undo.snapshot('eraser'); + continue; + } // Erase const newPath = items[i].subtract(lastPath); + newPath.insertBelow(items[i]); // Gather path segments const subpaths = []; @@ -236,11 +265,10 @@ class Blobbiness { const firstSeg = items[i].clone(); const intersections = firstSeg.getIntersections(lastPath); // keep first and last segments - if (intersections.length === 0) { - continue; - } for (let j = intersections.length - 1; j >= 0; j--) { - subpaths.push(firstSeg.splitAt(intersections[j])); + const split = firstSeg.splitAt(intersections[j]); + split.insertAbove(firstSeg); + subpaths.push(split); } subpaths.push(firstSeg); } diff --git a/src/containers/blob/broad-brush-helper.js b/src/containers/blob/broad-brush-helper.js index 464bc4a7..f4cf735c 100644 --- a/src/containers/blob/broad-brush-helper.js +++ b/src/containers/blob/broad-brush-helper.js @@ -20,7 +20,7 @@ class BroadBrushHelper { } onBroadMouseDown (event, tool, options) { - tool.minDistance = 1; + tool.minDistance = options.brushSize / 2; tool.maxDistance = options.brushSize; if (event.event.button > 0) return; // only first mouse button diff --git a/src/containers/blob/segment-brush-helper.js b/src/containers/blob/segment-brush-helper.js index 6a8837fe..8b716d50 100644 --- a/src/containers/blob/segment-brush-helper.js +++ b/src/containers/blob/segment-brush-helper.js @@ -18,6 +18,7 @@ class SegmentBrushHelper { constructor () { this.lastPoint = null; this.finalPath = null; + this.firstCircle = null; } onSegmentMouseDown (event, tool, options) { @@ -26,10 +27,11 @@ class SegmentBrushHelper { tool.minDistance = 1; tool.maxDistance = options.brushSize; - this.finalPath = new paper.Path.Circle({ + this.firstCircle = new paper.Path.Circle({ center: event.point, radius: options.brushSize / 2 }); + this.finalPath = this.firstCircle; stylePath(this.finalPath, options.isEraser); this.lastPoint = event.point; } @@ -78,8 +80,17 @@ class SegmentBrushHelper { // TODO: This smoothing tends to cut off large portions of the path! Would like to eventually // add back smoothing, maybe a custom implementation that only applies to a subset of the line? - // Smooth the path. - this.finalPath.simplify(2); + // Smooth the path. Make it unclosed first because smoothing of closed + // paths tends to cut off the path. + if (this.finalPath.segments && this.finalPath.segments.length > 4) { + this.finalPath.closed = false; + this.finalPath.simplify(2); + this.finalPath.closed = true; + // Merge again with the first point, since it gets distorted when we unclose the path. + const temp = this.finalPath.unite(this.firstCircle); + this.finalPath.remove(); + this.finalPath = temp; + } return this.finalPath; } } diff --git a/src/containers/brush-mode.jsx b/src/containers/brush-mode.jsx index e52b86db..b2549393 100644 --- a/src/containers/brush-mode.jsx +++ b/src/containers/brush-mode.jsx @@ -37,18 +37,13 @@ class BrushMode extends React.Component { return false; // Logic only component } activateTool () { + // TODO: Instead of clearing selection, consider a kind of "draw inside" + // analogous to how selection works with eraser + // pg.selection.clearSelection(); + // TODO: This is temporary until a component that provides the brush size is hooked up this.props.canvas.addEventListener('mousewheel', this.onScroll); this.blob.activateTool({isEraser: false, ...this.props.brushModeState}); - - // TODO Make sure a fill color is set on the brush - // if(!pg.stylebar.getFillColor()) { - // pg.stylebar.setFillColor(pg.stylebar.getStrokeColor()); - // pg.stylebar.setStrokeColor(null); - // } - - // TODO setup floating tool options panel in the editor - // pg.toolOptionPanel.setup(options, components, function() {}); } deactivateTool () { this.props.canvas.removeEventListener('mousewheel', this.onScroll);