Get move working

This commit is contained in:
DD 2017-09-13 15:17:59 -04:00
parent 3126c2ca7f
commit 0e91439edd
8 changed files with 75 additions and 63 deletions

View file

@ -4,4 +4,5 @@
margin: auto;
position: relative;
background-color: #fff;
image-rendering: pixelated;
}

View file

@ -24,12 +24,7 @@ class SelectMode extends React.Component {
bindAll(this, [
'activateTool',
'deactivateTool',
'getHitOptions',
'preProcessSelection',
'onMouseDown',
'onMouseMove',
'onMouseDrag',
'onMouseUp'
'getHitOptions'
]);
this._hitOptions = {
segments: true,
@ -71,48 +66,66 @@ class SelectMode extends React.Component {
selectRootItem();
this.tool = new paper.Tool();
const selectMode = this;
this.tool.onMouseDown = function (event) {
if (event.event.button > 0) return; // only first mouse button
this.props.clearHoveredItem();
if (!this.boundingBoxTool.onMouseDown(
event, event.modifiers.alt, event.modifiers.shift, true /* preselectedOnly */)) {
this.selectionBoxMode = true;
selectMode.props.clearHoveredItem();
if (!selectMode.boundingBoxTool.onMouseDown(
event,
event.modifiers.alt,
event.modifiers.shift,
selectMode.getHitOptions(false /* preseelectedOnly */))) {
selectMode.selectionBoxMode = true;
}
};
this.tool.onMouseMove = function (event) {
this.props.setHoveredItem(getHoveredItem(event, this.getHitOptions()));
const hoveredItem = getHoveredItem(event, selectMode.getHitOptions());
const oldHoveredItem = selectMode.props.hoveredItem;
if ((!hoveredItem && oldHoveredItem) || // There is no longer a hovered item
(hoveredItem && !oldHoveredItem) || // There is now a hovered item
(hoveredItem && oldHoveredItem && hoveredItem.id !== oldHoveredItem.id)) { // hovered item changed
if (oldHoveredItem) {
oldHoveredItem.remove();
}
selectMode.props.setHoveredItem(hoveredItem);
}
};
this.tool.onMouseDrag = function (event) {
if (event.event.button > 0) return; // only first mouse button
if (this.selectionBoxMode) {
this.selectionRect = rectSelect(event);
if (selectMode.selectionBoxMode) {
selectMode.selectionRect = rectSelect(event);
// Remove this rect on the next drag and up event
this.selectionRect.removeOnDrag();
selectMode.selectionRect.removeOnDrag();
} else {
this.boundingBoxTool.onMouseDrag(event);
selectMode.boundingBoxTool.onMouseDrag(event);
}
};
this.tool.onMouseUp = function (event) {
if (event.event.button > 0) return; // only first mouse button
if (this.selectionBoxMode) {
processRectangularSelection(event, this.selectionRect);
this.selectionRect.remove();
} else {
this.boundingBoxTool.onMouseUp(event);
this.props.onUpdateSvg();
if (selectMode.selectionBoxMode) {
if (selectMode.selectionRect) {
processRectangularSelection(event, selectMode.selectionRect);
selectMode.selectionRect.remove();
}
this.selectionBoxMode = false;
this.selectionRect = null;
selectMode.boundingBoxTool.setSelectionBounds();
} else {
selectMode.boundingBoxTool.onMouseUp(event);
selectMode.props.onUpdateSvg();
}
selectMode.selectionBoxMode = false;
selectMode.selectionRect = null;
};
this.tool.activate();
}
deactivateTool () {
this.props.setHoveredItem();
this.props.clearHoveredItem();
this.tool.remove();
this.tool = null;
this.hitResult = null;
@ -127,13 +140,15 @@ class SelectMode extends React.Component {
SelectMode.propTypes = {
clearHoveredItem: PropTypes.func.isRequired,
handleMouseDown: PropTypes.func.isRequired,
hoveredItem: PropTypes.instanceOf(paper.Item),
isSelectModeActive: PropTypes.bool.isRequired,
onUpdateSvg: PropTypes.func.isRequired,
setHoveredItem: PropTypes.func.isRequired
};
const mapStateToProps = state => ({
isSelectModeActive: state.scratchPaint.mode === Modes.SELECT
isSelectModeActive: state.scratchPaint.mode === Modes.SELECT,
hoveredItem: state.scratchPaint.hoveredItem
});
const mapDispatchToProps = dispatch => ({
setHoveredItem: hoveredItem => {

View file

@ -40,17 +40,18 @@ class BoundingBoxTool {
* @param {!MouseEvent} event The mouse event
* @param {boolean} clone Whether to clone on mouse down (e.g. alt key held)
* @param {boolean} multiselect Whether to multiselect on mouse down (e.g. shift key held)
* @param {boolean} preselectedOnly If true, only get hit results on items that are already selected
* @param {paper.hitOptions} hitOptions The options with which to detect whether mouse down has hit
* anything editable
* @return {boolean} True if there was a hit, false otherwise
*/
onMouseDown (event, clone, multiselect, preselectedOnly) {
const hitResults = paper.project.hitTestAll(event.point, this.getHitOptions(preselectedOnly));
onMouseDown (event, clone, multiselect, hitOptions) {
const hitResults = paper.project.hitTestAll(event.point, hitOptions);
if (!hitResults || hitResults.length === 0) {
if (!multiselect) {
this.removeBoundsPath();
clearSelection();
}
return null;
return false;
}
// Prefer scale to trigger over rotate, and scale and rotate to trigger over other hits
@ -65,14 +66,17 @@ class BoundingBoxTool {
hitResult = hitResults[i];
this.mode = Modes.ROTATE;
this._modeMap[this.mode].onMouseDown(hitResult, this.boundsPath, getSelectedItems());
} else {
}
}
if (!this.mode) {
this.mode = Modes.MOVE;
this._modeMap[this.mode].onMouseDown(hitResult, clone, multiselect);
}
}
// while transforming object, never show the bounds stuff
this.removeBoundsPath();
return true;
}
onMouseDrag (event) {
if (event.event.button > 0) return; // only first mouse button
@ -83,13 +87,8 @@ class BoundingBoxTool {
this._modeMap[this.mode].onMouseUp(event);
this.mode = null;
if (getSelectedItems().length <= 0) {
this.removeBoundsPath();
} else {
this.setSelectionBounds();
}
}
setSelectionBounds () {
this.removeBoundsPath();

View file

@ -1,7 +1,7 @@
import {isGroup} from '../group';
import {isCompoundPathItem, getRootItem} from '../item';
import {snapDeltaToAngle} from '../math';
import {clearSelection, cloneSelection, getSelectedItems, setItemSelection, setGroupSelection} from '../selection';
import {clearSelection, cloneSelection, getSelectedItems, setItemSelection} from '../selection';
class MoveTool {
constructor () {
@ -14,31 +14,22 @@ class MoveTool {
* @param {boolean} multiselect Whether to multiselect on mouse down (e.g. shift key held)
*/
onMouseDown (hitResult, clone, multiselect) {
const root = getRootItem(hitResult.item);
const item = isCompoundPathItem(root) || isGroup(root) ? root : hitResult.item;
if (!item.selected) {
// deselect all by default if multiselect isn't on
if (!multiselect) {
clearSelection();
}
// also needs some special love for compound paths and groups,
// as their children are not marked as "selected"
// deselect a currently selected item if multiselect is on
const root = getRootItem(hitResult.item);
if (isCompoundPathItem(root) || isGroup(root)) {
if (!root.selected) {
setGroupSelection(root, true);
setItemSelection(item, true);
} else if (multiselect) {
setGroupSelection(root, false);
}
} else if (multiselect && hitResult.item.selected) {
setItemSelection(hitResult.item, false);
} else {
setItemSelection(hitResult.item, true);
setItemSelection(item, false);
}
if (clone) cloneSelection();
this.selectedItems = getSelectedItems();
}
onMouseDrag (event) {
const dragVector = (event.point - event.downPoint);
const dragVector = event.point.subtract(event.downPoint);
for (const item of this.selectedItems) {
// add the position of the item before the drag started
// for later use in the snap calculation
@ -47,10 +38,9 @@ class MoveTool {
}
if (event.modifiers.shift) {
item.position = item.data.origPos +
snapDeltaToAngle(dragVector, Math.PI / 4);
item.position = item.data.origPos.add(snapDeltaToAngle(dragVector, Math.PI / 4));
} else {
item.position += event.delta;
item.position = item.data.origPos.add(dragVector);
}
}
}

View file

@ -16,7 +16,7 @@ const getHoveredItem = function (event, hitOptions) {
let hitResult;
for (const result of hitResults) {
if (!(result.item.data && result.item.data.noHover) && !hitResult.item.selected) {
if (!(result.item.data && result.item.data.noHover) && !result.item.selected) {
hitResult = result;
break;
}

View file

@ -15,4 +15,4 @@ const getGuideLayer = function () {
return guideLayer;
};
export default getGuideLayer;
export {getGuideLayer};

View file

@ -3,7 +3,8 @@ import keyMirror from 'keymirror';
const Modes = keyMirror({
BRUSH: null,
ERASER: null,
LINE: null
LINE: null,
SELECT: null
});
export default Modes;

View file

@ -1,3 +1,5 @@
import log from '../log/log';
const CHANGE_HOVERED = 'scratch-paint/hover/CHANGE_HOVERED';
const initialState = null;
@ -5,6 +7,10 @@ const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState;
switch (action.type) {
case CHANGE_HOVERED:
if (typeof action.hoveredItem === 'undefined') {
log.warn(`Hovered item should not be set to undefined. Use null.`);
return state;
}
return action.hoveredItem;
default:
return state;