diff --git a/src/containers/paper-canvas.jsx b/src/containers/paper-canvas.jsx index 28efc18b..565f23bf 100644 --- a/src/containers/paper-canvas.jsx +++ b/src/containers/paper-canvas.jsx @@ -157,7 +157,7 @@ class PaperCanvas extends React.Component { PaperCanvas.propTypes = { canvasRef: PropTypes.func, clearUndo: PropTypes.func.isRequired, - mode: PropTypes.instanceOf(Modes), + mode: PropTypes.oneOf(Object.values(Modes)), onUpdateSvg: PropTypes.func.isRequired, rotationCenterX: PropTypes.number, rotationCenterY: PropTypes.number, diff --git a/src/helper/blob-tools/blob.js b/src/helper/blob-tools/blob.js index d19c9276..f7a0be84 100644 --- a/src/helper/blob-tools/blob.js +++ b/src/helper/blob-tools/blob.js @@ -248,7 +248,8 @@ class Blobbiness { let items = getItems({ match: function (item) { return item.selected && blob.isMergeable(lastPath, item) && blob.touches(lastPath, item); - } + }, + class: paper.PathItem }); // Eraser didn't hit anything selected, so assume they meant to erase from all instead of from subset // and deselect the selection @@ -257,7 +258,8 @@ class Blobbiness { items = getItems({ match: function (item) { return blob.isMergeable(lastPath, item) && blob.touches(lastPath, item); - } + }, + class: paper.PathItem }); } @@ -317,42 +319,8 @@ class Blobbiness { } } - // Divide topologically separate shapes into their own compound paths, instead of - // everything being stuck together. - // Assume that result of erase operation returns clockwise paths for positive shapes - const clockwiseChildren = []; - const ccwChildren = []; if (newPath.children) { - for (let j = newPath.children.length - 1; j >= 0; j--) { - const child = newPath.children[j]; - if (child.isClockwise()) { - clockwiseChildren.push(child); - } else { - ccwChildren.push(child); - } - } - for (let j = 0; j < clockwiseChildren.length; j++) { - const cw = clockwiseChildren[j]; - cw.copyAttributes(newPath); - cw.fillColor = newPath.fillColor; - cw.strokeColor = newPath.strokeColor; - cw.strokeWidth = newPath.strokeWidth; - cw.insertAbove(items[i]); - - // Go backward since we are deleting elements - let newCw = cw; - for (let k = ccwChildren.length - 1; k >= 0; k--) { - const ccw = ccwChildren[k]; - if (this.firstEnclosesSecond(ccw, cw) || this.firstEnclosesSecond(cw, ccw)) { - const temp = newCw.subtract(ccw); - temp.insertAbove(newCw); - newCw.remove(); - newCw = temp; - ccw.remove(); - ccwChildren.splice(k, 1); - } - } - } + this.separateCompoundPath(newPath); newPath.remove(); } items[i].remove(); @@ -360,6 +328,44 @@ class Blobbiness { lastPath.remove(); } + separateCompoundPath (compoundPath) { + // Divide topologically separate shapes into their own compound paths, instead of + // everything being stuck together. + // Assume that result of erase operation returns clockwise paths for positive shapes + const clockwiseChildren = []; + const ccwChildren = []; + for (let j = compoundPath.children.length - 1; j >= 0; j--) { + const child = compoundPath.children[j]; + if (child.isClockwise()) { + clockwiseChildren.push(child); + } else { + ccwChildren.push(child); + } + } + for (let j = 0; j < clockwiseChildren.length; j++) { + const cw = clockwiseChildren[j]; + cw.copyAttributes(compoundPath); + cw.fillColor = compoundPath.fillColor; + cw.strokeColor = compoundPath.strokeColor; + cw.strokeWidth = compoundPath.strokeWidth; + cw.insertAbove(compoundPath); + + // Go backward since we are deleting elements + let newCw = cw; + for (let k = ccwChildren.length - 1; k >= 0; k--) { + const ccw = ccwChildren[k]; + if (this.firstEnclosesSecond(cw, ccw)) { + const temp = newCw.subtract(ccw); + temp.insertAbove(compoundPath); + newCw.remove(); + newCw = temp; + ccw.remove(); + ccwChildren.splice(k, 1); + } + } + } + } + colorMatch (existingPath, addedPath) { // Note: transparent fill colors do notdetect as touching return existingPath.getFillColor().equals(addedPath.getFillColor()) && @@ -388,10 +394,29 @@ class Blobbiness { return false; } + matchesAnyChild (group, path) { + for (const child of group.children) { + if (child.children && this.matchesAnyChild(path, child)) { + return true; + } + if (path === child) { + return true; + } + } + return false; + } + isMergeable (newPath, existingPath) { - return existingPath instanceof paper.PathItem && // path or compound path - existingPath !== this.cursorPreview && // don't merge with the mouse preview - existingPath !== newPath; // don't merge with self + // Path or compound path + if (!(existingPath instanceof paper.PathItem)) { + return; + } + if (newPath.children) { + if (this.matchesAnyChild(newPath, existingPath)) { // Don't merge with children of self + return false; + } + } + return existingPath !== newPath; // don't merge with self } deactivateTool () {