mirror of
https://github.com/scratchfoundation/scratch-paint.git
synced 2025-01-25 05:39:52 -05:00
Make fill tool work for outlines
This commit is contained in:
parent
2eab5048ac
commit
c81853b1b7
1 changed files with 32 additions and 9 deletions
|
@ -31,6 +31,8 @@ class FillTool extends paper.Tool {
|
||||||
|
|
||||||
// The path that's being hovered over.
|
// The path that's being hovered over.
|
||||||
this.fillItem = null;
|
this.fillItem = null;
|
||||||
|
// The style property that we're applying the color to (either fill or stroke).
|
||||||
|
this.fillProperty = null;
|
||||||
// If we're hovering over a hole in a compound path, we can't just recolor it. This is the
|
// If we're hovering over a hole in a compound path, we can't just recolor it. This is the
|
||||||
// added item that's the same shape as the hole that's drawn over the hole when we fill a hole.
|
// added item that's the same shape as the hole that's drawn over the hole when we fill a hole.
|
||||||
this.addedFillItem = null;
|
this.addedFillItem = null;
|
||||||
|
@ -43,14 +45,17 @@ class FillTool extends paper.Tool {
|
||||||
item.lastSegment.point.getDistance(item.firstSegment.point) < 8;
|
item.lastSegment.point.getDistance(item.firstSegment.point) < 8;
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
segments: true,
|
segments: false,
|
||||||
stroke: true,
|
stroke: true,
|
||||||
curves: true,
|
curves: false,
|
||||||
fill: true,
|
fill: true,
|
||||||
guide: false,
|
guide: false,
|
||||||
match: function (hitResult) {
|
match: function (hitResult) {
|
||||||
|
// Allow fills to be hit only if the item has a fill already or the path is closed/nearly closed
|
||||||
|
const hitFill = hitResult.item.hasFill() || hitResult.item.closed || isAlmostClosedPath(hitResult.item);
|
||||||
if (hitResult.item instanceof paper.Path &&
|
if (hitResult.item instanceof paper.Path &&
|
||||||
(hitResult.item.hasFill() || hitResult.item.closed || isAlmostClosedPath(hitResult.item))) {
|
// Disallow hits that don't qualify for the fill criteria, but only if they're fills
|
||||||
|
(hitFill || hitResult.type !== 'fill')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (hitResult.item instanceof paper.PointText) {
|
if (hitResult.item instanceof paper.PointText) {
|
||||||
|
@ -58,6 +63,12 @@ class FillTool extends paper.Tool {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hitUnfilledPaths: true,
|
hitUnfilledPaths: true,
|
||||||
|
// If the color is transparent/none, then we need to be able to hit "invisible" outlines so that we don't
|
||||||
|
// prevent ourselves from hitting an outline when we make it transparent via the fill preview, causing it to
|
||||||
|
// flicker back and forth between transparent/its previous color as we hit it, then stop hitting it, etc.
|
||||||
|
// If the color *is* visible, then don't hit "invisible" outlines, since this would add visible outlines to
|
||||||
|
// non-outlined shapes when you hovered over where their outlines would be.
|
||||||
|
hitUnstrokedPaths: this.gradientType === GradientTypes.SOLID && this.fillColor === null,
|
||||||
tolerance: FillTool.TOLERANCE / paper.view.zoom
|
tolerance: FillTool.TOLERANCE / paper.view.zoom
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -89,8 +100,13 @@ class FillTool extends paper.Tool {
|
||||||
this.setHoveredItem(hoveredItem ? hoveredItem.id : null);
|
this.setHoveredItem(hoveredItem ? hoveredItem.id : null);
|
||||||
}
|
}
|
||||||
const hitItem = hoveredItem ? hoveredItem.data.origItem : null;
|
const hitItem = hoveredItem ? hoveredItem.data.origItem : null;
|
||||||
|
const hitType = hoveredItem ? hoveredItem.data.hitResult.type : null;
|
||||||
|
|
||||||
|
// The hit "target" changes if we switch items or switch between fill/outline on the same item
|
||||||
|
const hitTargetChanged = hitItem !== this.fillItem || hitType !== this.fillProperty;
|
||||||
|
|
||||||
// Still hitting the same thing
|
// Still hitting the same thing
|
||||||
if ((!hitItem && !this.fillItem) || this.fillItem === hitItem) {
|
if (!hitTargetChanged) {
|
||||||
// Only radial gradient needs to be updated
|
// Only radial gradient needs to be updated
|
||||||
if (this.gradientType === GradientTypes.RADIAL) {
|
if (this.gradientType === GradientTypes.RADIAL) {
|
||||||
this._setFillItemColor(this.fillColor, this.fillColor2, this.gradientType, event.point);
|
this._setFillItemColor(this.fillColor, this.fillColor2, this.gradientType, event.point);
|
||||||
|
@ -106,14 +122,18 @@ class FillTool extends paper.Tool {
|
||||||
}
|
}
|
||||||
this.fillItemOrigColor = null;
|
this.fillItemOrigColor = null;
|
||||||
this.fillItem = null;
|
this.fillItem = null;
|
||||||
|
this.fillProperty = null;
|
||||||
}
|
}
|
||||||
if (hitItem) {
|
if (hitItem) {
|
||||||
this.fillItem = hitItem;
|
this.fillItem = hitItem;
|
||||||
this.fillItemOrigColor = hitItem.fillColor;
|
this.fillProperty = hitType;
|
||||||
if (hitItem.parent instanceof paper.CompoundPath && hitItem.area < 0) { // hole
|
const colorProp = hitType === 'fill' ? 'fillColor' : 'strokeColor';
|
||||||
|
this.fillItemOrigColor = hitItem[colorProp];
|
||||||
|
if (hitItem.parent instanceof paper.CompoundPath && hitItem.area < 0 && hitType === 'fill') { // hole
|
||||||
if (!this.fillColor) {
|
if (!this.fillColor) {
|
||||||
// Hole filled with transparent is no-op
|
// Hole filled with transparent is no-op
|
||||||
this.fillItem = null;
|
this.fillItem = null;
|
||||||
|
this.fillProperty = null;
|
||||||
this.fillItemOrigColor = null;
|
this.fillItemOrigColor = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +147,7 @@ class FillTool extends paper.Tool {
|
||||||
expandBy(this.addedFillItem, .1);
|
expandBy(this.addedFillItem, .1);
|
||||||
this.addedFillItem.insertAbove(hitItem.parent);
|
this.addedFillItem.insertAbove(hitItem.parent);
|
||||||
} else if (this.fillItem.parent instanceof paper.CompoundPath) {
|
} else if (this.fillItem.parent instanceof paper.CompoundPath) {
|
||||||
this.fillItemOrigColor = hitItem.parent.fillColor;
|
this.fillItemOrigColor = hitItem.parent[colorProp];
|
||||||
}
|
}
|
||||||
this._setFillItemColor(this.fillColor, this.fillColor2, this.gradientType, event.point);
|
this._setFillItemColor(this.fillColor, this.fillColor2, this.gradientType, event.point);
|
||||||
}
|
}
|
||||||
|
@ -163,6 +183,7 @@ class FillTool extends paper.Tool {
|
||||||
|
|
||||||
this.clearHoveredItem();
|
this.clearHoveredItem();
|
||||||
this.fillItem = null;
|
this.fillItem = null;
|
||||||
|
this.fillProperty = null;
|
||||||
this.addedFillItem = null;
|
this.addedFillItem = null;
|
||||||
this.fillItemOrigColor = null;
|
this.fillItemOrigColor = null;
|
||||||
this.onUpdateImage();
|
this.onUpdateImage();
|
||||||
|
@ -178,12 +199,13 @@ class FillTool extends paper.Tool {
|
||||||
_setFillItemColor (color1, color2, gradientType, pointerLocation) {
|
_setFillItemColor (color1, color2, gradientType, pointerLocation) {
|
||||||
const item = this._getFillItem();
|
const item = this._getFillItem();
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
|
const colorProp = this.fillProperty === 'fill' ? 'fillColor' : 'strokeColor';
|
||||||
// Only create a gradient if specifically requested, else use color1 directly
|
// Only create a gradient if specifically requested, else use color1 directly
|
||||||
// This ensures we do not set a gradient by accident (see scratch-paint#830).
|
// This ensures we do not set a gradient by accident (see scratch-paint#830).
|
||||||
if (gradientType && gradientType !== GradientTypes.SOLID) {
|
if (gradientType && gradientType !== GradientTypes.SOLID) {
|
||||||
item.fillColor = createGradientObject(color1, color2, gradientType, item.bounds, pointerLocation);
|
item[colorProp] = createGradientObject(color1, color2, gradientType, item.bounds, pointerLocation);
|
||||||
} else {
|
} else {
|
||||||
item.fillColor = color1;
|
item[colorProp] = color1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_getFillItem () {
|
_getFillItem () {
|
||||||
|
@ -199,6 +221,7 @@ class FillTool extends paper.Tool {
|
||||||
this._setFillItemColor(this.fillItemOrigColor);
|
this._setFillItemColor(this.fillItemOrigColor);
|
||||||
this.fillItemOrigColor = null;
|
this.fillItemOrigColor = null;
|
||||||
this.fillItem = null;
|
this.fillItem = null;
|
||||||
|
this.fillProperty = null;
|
||||||
}
|
}
|
||||||
this.clearHoveredItem();
|
this.clearHoveredItem();
|
||||||
this.setHoveredItem = null;
|
this.setHoveredItem = null;
|
||||||
|
|
Loading…
Reference in a new issue