mirror of
https://github.com/scratchfoundation/scratch-paint.git
synced 2024-12-23 05:52:42 -05:00
nudge
This commit is contained in:
parent
1ff5fdff38
commit
f3dcc54bf3
4 changed files with 113 additions and 27 deletions
|
@ -1,6 +1,6 @@
|
|||
import paper from '@scratch/paper';
|
||||
import {snapDeltaToAngle} from '../math';
|
||||
import {clearSelection, getSelectedLeafItems} from '../selection';
|
||||
import {clearSelection, getSelectedLeafItems, getSelectedSegments} from '../selection';
|
||||
import {HANDLE_RATIO} from '../math';
|
||||
|
||||
/** Subtool of ReshapeTool for moving control points. */
|
||||
|
@ -146,17 +146,14 @@ class PointTool {
|
|||
|
||||
const dragVector = event.point.subtract(event.downPoint);
|
||||
|
||||
for (const item of this.selectedItems) {
|
||||
if (!item.segments) {
|
||||
return;
|
||||
}
|
||||
for (const seg of item.segments) {
|
||||
const selectedSegments = getSelectedSegments();
|
||||
for (const seg of selectedSegments) {
|
||||
// add the point of the segment before the drag started
|
||||
// for later use in the snap calculation
|
||||
if (!seg.origPoint) {
|
||||
seg.origPoint = seg.point.clone();
|
||||
}
|
||||
if (seg.selected) {
|
||||
|
||||
if (event.modifiers.shift) {
|
||||
seg.point = seg.origPoint.add(snapDeltaToAngle(dragVector, Math.PI / 4));
|
||||
} else {
|
||||
|
@ -164,22 +161,16 @@ class PointTool {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onMouseUp () {
|
||||
// resetting the items and segments origin points for the next usage
|
||||
let moved = false;
|
||||
for (const item of this.selectedItems) {
|
||||
if (!item.segments) {
|
||||
return;
|
||||
}
|
||||
for (const seg of item.segments) {
|
||||
const selectedSegments = getSelectedSegments();
|
||||
for (const seg of selectedSegments) {
|
||||
if (seg.origPoint && !seg.equals(seg.origPoint)) {
|
||||
moved = true;
|
||||
}
|
||||
seg.origPoint = null;
|
||||
}
|
||||
}
|
||||
|
||||
// If no drag occurred between mouse down and mouse up, then we can go through with deselect
|
||||
// and delete
|
||||
|
|
|
@ -5,6 +5,7 @@ import keyMirror from 'keymirror';
|
|||
import Modes from '../../lib/modes';
|
||||
import {getHoveredItem} from '../hover';
|
||||
import {getRootItem, isPGTextItem} from '../item';
|
||||
import {getSelectedLeafItems, getSelectedSegments} from '../selection';
|
||||
import MoveTool from './move-tool';
|
||||
import PointTool from './point-tool';
|
||||
import HandleTool from './handle-tool';
|
||||
|
@ -67,6 +68,8 @@ class ReshapeTool extends paper.Tool {
|
|||
this.onMouseMove = this.handleMouseMove;
|
||||
this.onMouseDrag = this.handleMouseDrag;
|
||||
this.onMouseUp = this.handleMouseUp;
|
||||
this.onKeyUp = this.handleKeyUp;
|
||||
this.onKeyDown = this.handleKeyDown;
|
||||
|
||||
paper.settings.handleSize = 8;
|
||||
}
|
||||
|
@ -228,6 +231,44 @@ class ReshapeTool extends paper.Tool {
|
|||
this.mode = ReshapeModes.SELECTION_BOX;
|
||||
this.active = false;
|
||||
}
|
||||
handleKeyDown (event) {
|
||||
const nudgeAmount = 1 / paper.view.zoom;
|
||||
const selected = getSelectedLeafItems();
|
||||
if (selected.length === 0) return;
|
||||
|
||||
let translation;
|
||||
if (event.key === 'up') {
|
||||
translation = new paper.Point(0, -nudgeAmount);
|
||||
} else if (event.key === 'down') {
|
||||
translation = new paper.Point(0, nudgeAmount);
|
||||
} else if (event.key === 'left') {
|
||||
translation = new paper.Point(-nudgeAmount, 0);
|
||||
} else if (event.key === 'right') {
|
||||
translation = new paper.Point(nudgeAmount, 0);
|
||||
}
|
||||
|
||||
if (translation) {
|
||||
const segments = getSelectedSegments();
|
||||
// If no segments are selected, translate selected paths
|
||||
if (segments.length === 0) {
|
||||
for (const item of selected) {
|
||||
item.translate(translation);
|
||||
}
|
||||
} else { // Translate segments
|
||||
for (const seg of segments) {
|
||||
seg.point = seg.point.add(translation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
handleKeyUp (event) {
|
||||
const selected = getSelectedLeafItems();
|
||||
if (selected.length === 0) return;
|
||||
|
||||
if (event.key === 'up' || event.key === 'down' || event.key === 'left' || event.key === 'right') {
|
||||
this.onUpdateSvg();
|
||||
}
|
||||
}
|
||||
deactivateTool () {
|
||||
paper.settings.handleSize = 0;
|
||||
this.clearHoveredItem();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Modes from '../../lib/modes';
|
||||
|
||||
import {getHoveredItem} from '../hover';
|
||||
import {selectRootItem} from '../selection';
|
||||
import {getSelectedRootItems, selectRootItem} from '../selection';
|
||||
import BoundingBoxTool from './bounding-box-tool';
|
||||
import SelectionBoxTool from './selection-box-tool';
|
||||
import paper from '@scratch/paper';
|
||||
|
@ -42,6 +42,8 @@ class SelectTool extends paper.Tool {
|
|||
this.onMouseMove = this.handleMouseMove;
|
||||
this.onMouseDrag = this.handleMouseDrag;
|
||||
this.onMouseUp = this.handleMouseUp;
|
||||
this.onKeyUp = this.handleKeyUp;
|
||||
this.onKeyDown = this.handleKeyDown;
|
||||
|
||||
selectRootItem();
|
||||
setSelectedItems();
|
||||
|
@ -131,6 +133,37 @@ class SelectTool extends paper.Tool {
|
|||
this.selectionBoxMode = false;
|
||||
this.active = false;
|
||||
}
|
||||
handleKeyDown (event) {
|
||||
const nudgeAmount = 1 / paper.view.zoom;
|
||||
const selected = getSelectedRootItems();
|
||||
if (selected.length === 0) return;
|
||||
|
||||
let translation;
|
||||
if (event.key === 'up') {
|
||||
translation = new paper.Point(0, -nudgeAmount);
|
||||
} else if (event.key === 'down') {
|
||||
translation = new paper.Point(0, nudgeAmount);
|
||||
} else if (event.key === 'left') {
|
||||
translation = new paper.Point(-nudgeAmount, 0);
|
||||
} else if (event.key === 'right') {
|
||||
translation = new paper.Point(nudgeAmount, 0);
|
||||
}
|
||||
|
||||
if (translation) {
|
||||
for (const item of selected) {
|
||||
item.translate(translation);
|
||||
}
|
||||
}
|
||||
this.boundingBoxTool.setSelectionBounds();
|
||||
}
|
||||
handleKeyUp (event) {
|
||||
const selected = getSelectedRootItems();
|
||||
if (selected.length === 0) return;
|
||||
|
||||
if (event.key === 'up' || event.key === 'down' || event.key === 'left' || event.key === 'right') {
|
||||
this.onUpdateSvg();
|
||||
}
|
||||
}
|
||||
deactivateTool () {
|
||||
this.clearHoveredItem();
|
||||
this.boundingBoxTool.removeBoundsPath();
|
||||
|
|
|
@ -175,6 +175,26 @@ const getSelectedLeafItems = function () {
|
|||
return items;
|
||||
};
|
||||
|
||||
/**
|
||||
* This gets all selected path segments.
|
||||
* @return {Array<paper.Segment>} selected segments
|
||||
*/
|
||||
const getSelectedSegments = function () {
|
||||
const selected = getSelectedLeafItems();
|
||||
const segments = [];
|
||||
for (const item of selected) {
|
||||
if (!item.segments) {
|
||||
continue;
|
||||
}
|
||||
for (const seg of item.segments) {
|
||||
if (seg.selected) {
|
||||
segments.push(seg);
|
||||
}
|
||||
}
|
||||
}
|
||||
return segments;
|
||||
};
|
||||
|
||||
const _deleteItemSelection = function (items, onUpdateSvg) {
|
||||
// @todo: Update toolbar state on change
|
||||
if (items.length === 0) {
|
||||
|
@ -408,6 +428,7 @@ export {
|
|||
setItemSelection,
|
||||
getSelectedLeafItems,
|
||||
getSelectedRootItems,
|
||||
getSelectedSegments,
|
||||
processRectangularSelection,
|
||||
selectRootItem,
|
||||
shouldShowSelectAll
|
||||
|
|
Loading…
Reference in a new issue