mirror of
https://github.com/scratchfoundation/scratch-paint.git
synced 2024-12-22 21:42:30 -05:00
Bring over new bug fixes from papergrapher
This commit is contained in:
parent
a875bee81c
commit
6ede893585
4 changed files with 51 additions and 17 deletions
|
@ -226,8 +226,37 @@ class Blobbiness {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = items.length - 1; i >= 0; i--) {
|
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
|
// Erase
|
||||||
const newPath = items[i].subtract(lastPath);
|
const newPath = items[i].subtract(lastPath);
|
||||||
|
newPath.insertBelow(items[i]);
|
||||||
|
|
||||||
// Gather path segments
|
// Gather path segments
|
||||||
const subpaths = [];
|
const subpaths = [];
|
||||||
|
@ -236,11 +265,10 @@ class Blobbiness {
|
||||||
const firstSeg = items[i].clone();
|
const firstSeg = items[i].clone();
|
||||||
const intersections = firstSeg.getIntersections(lastPath);
|
const intersections = firstSeg.getIntersections(lastPath);
|
||||||
// keep first and last segments
|
// keep first and last segments
|
||||||
if (intersections.length === 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (let j = intersections.length - 1; j >= 0; j--) {
|
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);
|
subpaths.push(firstSeg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ class BroadBrushHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
onBroadMouseDown (event, tool, options) {
|
onBroadMouseDown (event, tool, options) {
|
||||||
tool.minDistance = 1;
|
tool.minDistance = options.brushSize / 2;
|
||||||
tool.maxDistance = options.brushSize;
|
tool.maxDistance = options.brushSize;
|
||||||
if (event.event.button > 0) return; // only first mouse button
|
if (event.event.button > 0) return; // only first mouse button
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ class SegmentBrushHelper {
|
||||||
constructor () {
|
constructor () {
|
||||||
this.lastPoint = null;
|
this.lastPoint = null;
|
||||||
this.finalPath = null;
|
this.finalPath = null;
|
||||||
|
this.firstCircle = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSegmentMouseDown (event, tool, options) {
|
onSegmentMouseDown (event, tool, options) {
|
||||||
|
@ -26,10 +27,11 @@ class SegmentBrushHelper {
|
||||||
tool.minDistance = 1;
|
tool.minDistance = 1;
|
||||||
tool.maxDistance = options.brushSize;
|
tool.maxDistance = options.brushSize;
|
||||||
|
|
||||||
this.finalPath = new paper.Path.Circle({
|
this.firstCircle = new paper.Path.Circle({
|
||||||
center: event.point,
|
center: event.point,
|
||||||
radius: options.brushSize / 2
|
radius: options.brushSize / 2
|
||||||
});
|
});
|
||||||
|
this.finalPath = this.firstCircle;
|
||||||
stylePath(this.finalPath, options.isEraser);
|
stylePath(this.finalPath, options.isEraser);
|
||||||
this.lastPoint = event.point;
|
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
|
// 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?
|
// add back smoothing, maybe a custom implementation that only applies to a subset of the line?
|
||||||
|
|
||||||
// Smooth the path.
|
// Smooth the path. Make it unclosed first because smoothing of closed
|
||||||
this.finalPath.simplify(2);
|
// 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;
|
return this.finalPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,18 +37,13 @@ class BrushMode extends React.Component {
|
||||||
return false; // Logic only component
|
return false; // Logic only component
|
||||||
}
|
}
|
||||||
activateTool () {
|
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
|
// TODO: This is temporary until a component that provides the brush size is hooked up
|
||||||
this.props.canvas.addEventListener('mousewheel', this.onScroll);
|
this.props.canvas.addEventListener('mousewheel', this.onScroll);
|
||||||
this.blob.activateTool({isEraser: false, ...this.props.brushModeState});
|
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 () {
|
deactivateTool () {
|
||||||
this.props.canvas.removeEventListener('mousewheel', this.onScroll);
|
this.props.canvas.removeEventListener('mousewheel', this.onScroll);
|
||||||
|
|
Loading…
Reference in a new issue