From a04f1276f8e040e996588cae9fd91e9c476a49d0 Mon Sep 17 00:00:00 2001 From: Florrie <9948030+towerofnix@users.noreply.github.com> Date: Wed, 28 Nov 2018 14:16:20 -0400 Subject: [PATCH] Make circle (shift-oval) tool work for any direction dragged (#774) --- src/helper/bit-tools/oval-tool.js | 7 ++++++- src/helper/bit-tools/rect-tool.js | 10 ++++++--- src/helper/math.js | 34 +++++++++++++++++++++++++++++++ src/helper/tools/oval-tool.js | 8 ++++++-- src/helper/tools/rect-tool.js | 13 +++++++----- 5 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/helper/bit-tools/oval-tool.js b/src/helper/bit-tools/oval-tool.js index 3c4bd2e8..21fac4ee 100644 --- a/src/helper/bit-tools/oval-tool.js +++ b/src/helper/bit-tools/oval-tool.js @@ -3,6 +3,7 @@ import Modes from '../../lib/modes'; import {commitOvalToBitmap} from '../bitmap'; import {getRaster} from '../layer'; import {clearSelection} from '../selection'; +import {getSquareDimensions} from '../math'; import BoundingBoxTool from '../selection-tools/bounding-box-tool'; import NudgeTool from '../selection-tools/nudge-tool'; @@ -151,13 +152,17 @@ class OvalTool extends paper.Tool { const downPoint = new paper.Point(event.downPoint.x, event.downPoint.y); const point = new paper.Point(event.point.x, event.point.y); + const squareDimensions = getSquareDimensions(event.downPoint, event.point); if (event.modifiers.shift) { - this.oval.size = new paper.Point(event.downPoint.x - event.point.x, event.downPoint.x - event.point.x); + this.oval.size = squareDimensions.size.abs(); } else { this.oval.size = downPoint.subtract(point); } + if (event.modifiers.alt) { this.oval.position = downPoint; + } else if (event.modifiers.shift) { + this.oval.position = squareDimensions.position; } else { this.oval.position = downPoint.subtract(this.oval.size.multiply(0.5)); } diff --git a/src/helper/bit-tools/rect-tool.js b/src/helper/bit-tools/rect-tool.js index 8408f3ad..f7a4ee5d 100644 --- a/src/helper/bit-tools/rect-tool.js +++ b/src/helper/bit-tools/rect-tool.js @@ -3,6 +3,7 @@ import Modes from '../../lib/modes'; import {commitRectToBitmap} from '../bitmap'; import {getRaster} from '../layer'; import {clearSelection} from '../selection'; +import {getSquareDimensions} from '../math'; import BoundingBoxTool from '../selection-tools/bounding-box-tool'; import NudgeTool from '../selection-tools/nudge-tool'; @@ -133,10 +134,11 @@ class RectTool extends paper.Tool { const dimensions = event.point.subtract(event.downPoint); const baseRect = new paper.Rectangle(event.downPoint, event.point); + const squareDimensions = getSquareDimensions(event.downPoint, event.point); if (event.modifiers.shift) { - baseRect.height = baseRect.width; - dimensions.y = event.downPoint.y > event.point.y ? -Math.abs(baseRect.width) : Math.abs(baseRect.width); + baseRect.size = squareDimensions.size.abs(); } + if (this.rect) this.rect.remove(); this.rect = new paper.Shape.Rectangle(baseRect); if (this.filled) { @@ -152,6 +154,8 @@ class RectTool extends paper.Tool { if (event.modifiers.alt) { this.rect.position = event.downPoint; + } else if (event.modifiers.shift) { + this.rect.position = squareDimensions.position; } else { this.rect.position = event.downPoint.add(dimensions.multiply(.5)); } @@ -184,7 +188,7 @@ class RectTool extends paper.Tool { if (!this.rect || !this.rect.isInserted()) return; commitRectToBitmap(this.rect, getRaster()); - + this.rect.remove(); this.rect = null; } diff --git a/src/helper/math.js b/src/helper/math.js index a02fcee3..41f8d668 100644 --- a/src/helper/math.js +++ b/src/helper/math.js @@ -131,6 +131,39 @@ const scaleWithStrokes = function (root, factor, pivot) { root.scale(factor, pivot); }; +/** + * Get the size and position of a square, as in if the user were holding the shift key down while drawing the shape, + * from the point where the drag started and the point where the mouse is currently positioned. (Note: This also works + * for shapes like circles ("square ovals"), which fill the same dimensions.) + * @param {!paper.Point} startPos The point where the user started dragging + * @param {!paper.Point} eventPoint The point where the user has currently dragged to + * @return {object} Information about the size and position of how the square should be drawn + */ +const getSquareDimensions = function (startPos, eventPoint) { + // These variables are used for determining the relative quadrant that the shape will appear in. + // So if you drag up and right, it'll show up above and to the right of where you started dragging, etc. + let offsetX = eventPoint.x - startPos.x; + let offsetY = eventPoint.y - startPos.y; + + // If the offset variables are zero, the shape ends up having zero width or height, which is bad. + // Deal with this by forcing them to be non-zero (we arbitrarily choose 1; any non-zero value would work). + offsetX = offsetX ? offsetX : 1; + offsetY = offsetY ? offsetY : 1; + + // The length of the shape is the greater of the X and Y offsets. + const offsetDistance = eventPoint.subtract(startPos).abs(); + const length = Math.max(offsetDistance.x, offsetDistance.y); + + const size = new paper.Point( + length * offsetX / Math.abs(offsetX), + length * offsetY / Math.abs(offsetY) + ); + + const position = startPos.add(size.multiply(0.5)); + + return {size, position}; +}; + export { HANDLE_RATIO, checkPointsClose, @@ -138,6 +171,7 @@ export { expandBy, getRandomInt, getRandomBoolean, + getSquareDimensions, scaleWithStrokes, snapDeltaToAngle, sortItemsByZIndex diff --git a/src/helper/tools/oval-tool.js b/src/helper/tools/oval-tool.js index f9c248be..07286862 100644 --- a/src/helper/tools/oval-tool.js +++ b/src/helper/tools/oval-tool.js @@ -2,6 +2,7 @@ import paper from '@scratch/paper'; import Modes from '../../lib/modes'; import {styleShape} from '../style-path'; import {clearSelection} from '../selection'; +import {getSquareDimensions} from '../math'; import BoundingBoxTool from '../selection-tools/bounding-box-tool'; import NudgeTool from '../selection-tools/nudge-tool'; @@ -88,17 +89,20 @@ class OvalTool extends paper.Tool { const downPoint = new paper.Point(event.downPoint.x, event.downPoint.y); const point = new paper.Point(event.point.x, event.point.y); + const squareDimensions = getSquareDimensions(event.downPoint, event.point); if (event.modifiers.shift) { - this.oval.size = new paper.Point(event.downPoint.x - event.point.x, event.downPoint.x - event.point.x); + this.oval.size = squareDimensions.size.abs(); } else { this.oval.size = downPoint.subtract(point); } + if (event.modifiers.alt) { this.oval.position = downPoint; + } else if (event.modifiers.shift) { + this.oval.position = squareDimensions.position; } else { this.oval.position = downPoint.subtract(this.oval.size.multiply(0.5)); } - } handleMouseUp (event) { if (event.event.button > 0 || !this.active) return; // only first mouse button diff --git a/src/helper/tools/rect-tool.js b/src/helper/tools/rect-tool.js index a890c323..e1cc31e9 100644 --- a/src/helper/tools/rect-tool.js +++ b/src/helper/tools/rect-tool.js @@ -2,6 +2,7 @@ import paper from '@scratch/paper'; import Modes from '../../lib/modes'; import {styleShape} from '../style-path'; import {clearSelection} from '../selection'; +import {getSquareDimensions} from '../math'; import BoundingBoxTool from '../selection-tools/bounding-box-tool'; import NudgeTool from '../selection-tools/nudge-tool'; @@ -85,18 +86,20 @@ class RectTool extends paper.Tool { this.rect.remove(); } - const dimensions = event.point.subtract(event.downPoint); const rect = new paper.Rectangle(event.downPoint, event.point); + const squareDimensions = getSquareDimensions(event.downPoint, event.point); if (event.modifiers.shift) { - rect.height = rect.width; - dimensions.y = event.downPoint.y > event.point.y ? -Math.abs(rect.width) : Math.abs(rect.width); + rect.size = squareDimensions.size.abs(); } - this.rect = new paper.Path.Rectangle(rect); + this.rect = new paper.Path.Rectangle(rect); if (event.modifiers.alt) { this.rect.position = event.downPoint; + } else if (event.modifiers.shift) { + this.rect.position = squareDimensions.position; } else { - this.rect.position = event.downPoint.add(dimensions.multiply(.5)); + const dimensions = event.point.subtract(event.downPoint); + this.rect.position = event.downPoint.add(dimensions.multiply(0.5)); } styleShape(this.rect, this.colorState);