mirror of
https://github.com/Doodle3D/Doodle3D-Core.git
synced 2024-12-23 03:23:48 +01:00
use raf instead of request animation frame
This commit is contained in:
parent
7aac749d77
commit
4b08f1fbbe
15
package-lock.json
generated
15
package-lock.json
generated
@ -4393,6 +4393,21 @@
|
|||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz",
|
||||||
"integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw="
|
"integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw="
|
||||||
},
|
},
|
||||||
|
"raf": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-pDP/NMRAXoTfrhCfyfSEwJAKLaxBU9eApMeBPB1TkDouZmvPerIClV8lTAd+uF8ZiTaVl69e1FCxQrAd/VTjGw==",
|
||||||
|
"requires": {
|
||||||
|
"performance-now": "2.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"performance-now": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||||
|
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"randomatic": {
|
"randomatic": {
|
||||||
"version": "1.1.7",
|
"version": "1.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
"memoizee": "^0.3.9",
|
"memoizee": "^0.3.9",
|
||||||
"pouchdb": "^6.3.4",
|
"pouchdb": "^6.3.4",
|
||||||
"proptypes": "^1.1.0",
|
"proptypes": "^1.1.0",
|
||||||
|
"raf": "^3.4.0",
|
||||||
"raw-loader": "^0.5.1",
|
"raw-loader": "^0.5.1",
|
||||||
"react": "^16.0.0",
|
"react": "^16.0.0",
|
||||||
"react-jss": "^8.0.0",
|
"react-jss": "^8.0.0",
|
||||||
|
496
src/actions/index.js
Normal file
496
src/actions/index.js
Normal file
@ -0,0 +1,496 @@
|
|||||||
|
import { ActionCreators as undo } from 'redux-undo';
|
||||||
|
import * as notification from 'react-notification-system-redux';
|
||||||
|
import { routerActions as router } from 'react-router-redux';
|
||||||
|
import * as selectionUtils from '../utils/selectionUtils.js';
|
||||||
|
import { calculatePointInImage, decomposeMatrix } from '../utils/matrixUtils.js';
|
||||||
|
import { loadImage, prepareImage } from '../utils/imageUtils.js';
|
||||||
|
import * as traceUtils from '../utils/traceUtils.js';
|
||||||
|
import { createThrottle } from '../utils/async.js';
|
||||||
|
import { tween } from '../utils/tweenUtils.js';
|
||||||
|
import { DEFAULT_TRACE_TOLERANCE, MAX_TRACE_TOLERANCE } from '../constants/d2Constants.js';
|
||||||
|
import * as d2Tools from '../constants/d2Tools.js';
|
||||||
|
import { Matrix } from 'cal';
|
||||||
|
// import createDebug from 'debug';
|
||||||
|
// const debug = createDebug('d3d:actions');
|
||||||
|
|
||||||
|
export { undo };
|
||||||
|
|
||||||
|
export const ADD_OBJECT = 'ADD_OBJECT';
|
||||||
|
export const D2_DRAG_START = 'D2_DRAG_START';
|
||||||
|
export const D2_DRAG = 'D2_DRAG';
|
||||||
|
export const D2_DRAG_END = 'D2_DRAG_END';
|
||||||
|
export const D2_SECOND_DRAG_START = 'D2_SECOND_DRAG_START';
|
||||||
|
export const D2_SECOND_DRAG = 'D2_SECOND_DRAG';
|
||||||
|
export const D2_SECOND_DRAG_END = 'D2_SECOND_DRAG_END';
|
||||||
|
export const D2_TAP = 'D2_TAP';
|
||||||
|
export const D2_MOUSE_WHEEL = 'D2_MOUSE_WHEEL';
|
||||||
|
export const D2_MULTITOUCH_START = 'D2_MULTITOUCH_START';
|
||||||
|
export const D2_MULTITOUCH = 'D2_MULTITOUCH';
|
||||||
|
export const D2_MULTITOUCH_END = 'D2_MULTITOUCH_END';
|
||||||
|
export const D3_DRAG_START = 'D3_DRAG_START';
|
||||||
|
export const D3_DRAG = 'D3_DRAG';
|
||||||
|
export const D3_DRAG_END = 'D3_DRAG_END';
|
||||||
|
export const D3_SECOND_DRAG_START = 'D3_SECOND_DRAG_START';
|
||||||
|
export const D3_SECOND_DRAG = 'D3_SECOND_DRAG';
|
||||||
|
export const D3_SECOND_DRAG_END = 'D3_SECOND_DRAG_END';
|
||||||
|
export const D3_TAP = 'D3_TAP';
|
||||||
|
export const D3_MOUSE_WHEEL = 'D3_MOUSE_WHEEL';
|
||||||
|
export const D3_MULTITOUCH_START = 'D3_MULTITOUCH_START';
|
||||||
|
export const D3_MULTITOUCH = 'D3_MULTITOUCH';
|
||||||
|
export const D3_MULTITOUCH_END = 'D3_MULTITOUCH_END';
|
||||||
|
export const D2_CHANGE_TOOL = 'D2_CHANGE_TOOL';
|
||||||
|
export const D3_CHANGE_TOOL = 'D3_CHANGE_TOOL';
|
||||||
|
export const CONTEXT_CHANGE_TOOL = 'CONTEXT_CHANGE_TOOL';
|
||||||
|
export const HEIGHT_START = 'HEIGHT_START';
|
||||||
|
export const HEIGHT = 'HEIGHT';
|
||||||
|
export const HEIGHT_END = 'HEIGHT_END';
|
||||||
|
export const TWIST_START = 'TWIST_START';
|
||||||
|
export const TWIST = 'TWIST';
|
||||||
|
export const TWIST_END = 'TWIST_END';
|
||||||
|
export const SCULPT_START = 'SCULPT_START';
|
||||||
|
export const SCULPT = 'SCULPT';
|
||||||
|
export const SCULPT_END = 'SCULPT_END';
|
||||||
|
export const ADD_SCULPT_HANDLE = 'ADD_SCULPT_HANDLE';
|
||||||
|
export const REMOVE_SCULPT_HANDLE = 'REMOVE_SCULPT_HANDLE';
|
||||||
|
export const STAMP = 'STAMP';
|
||||||
|
export const BED_SELECT = 'BED_SELECT';
|
||||||
|
export const CLEAR = 'CLEAR';
|
||||||
|
export const TRANSFORM_START = 'TRANSFORM_START';
|
||||||
|
export const TRANSFORM = 'TRANSFORM';
|
||||||
|
export const TRANSFORM_END = 'TRANSFORM_END';
|
||||||
|
export const DRAG_SELECT = 'DRAG_SELECT';
|
||||||
|
export const MULTITOUCH_TRANSFORM_START = 'MULTITOUCH_TRANSFORM_START';
|
||||||
|
export const MULTITOUCH_TRANSFORM = 'MULTITOUCH_TRANSFORM';
|
||||||
|
export const MULTITOUCH_TRANSFORM_END = 'MULTITOUCH_TRANSFORM_END';
|
||||||
|
export const SELECT = 'SELECT';
|
||||||
|
export const UPDATE_MATRIX = 'UPDATE_MATRIX';
|
||||||
|
export const DESELECT = 'DESELECT';
|
||||||
|
export const TOGGLE_SELECT = 'TOGGLE_SELECT';
|
||||||
|
export const DESELECT_ALL = 'DESELECT_ALL';
|
||||||
|
export const SELECT_ALL = 'SELECT_ALL';
|
||||||
|
export const DELETE_SELECTION = 'DELETE_SELECTION';
|
||||||
|
export const DUPLICATE_SELECTION = 'DUPLICATE_SELECTION';
|
||||||
|
export const ALIGN = 'ALIGN';
|
||||||
|
export const ADD_IMAGE = 'ADD_IMAGE';
|
||||||
|
export const D2_TEXT_INIT = 'D2_TEXT_INIT';
|
||||||
|
export const D2_TEXT_INPUT_CHANGE = 'D2_TEXT_INPUT_CHANGE';
|
||||||
|
export const D2_TEXT_ADD = 'D2_TEXT_ADD';
|
||||||
|
export const UNION = 'UNION';
|
||||||
|
export const INTERSECT = 'INTERSECT';
|
||||||
|
export const MOVE_SELECTION = 'MOVE_SELECTION';
|
||||||
|
export const TRACE_DRAG = 'TRACE_DRAG';
|
||||||
|
export const TRACE_DRAG_END = 'TRACE_DRAG_END';
|
||||||
|
export const TRACE_TAP = 'TRACE_TAP';
|
||||||
|
export const FLOOD_FILL = 'FLOOD_FILL';
|
||||||
|
export const TRACE_FLOOD_FILL = 'TRACE_FLOOD_FILL';
|
||||||
|
export const MENU_OPEN = 'MENU_OPEN';
|
||||||
|
export const MENU_CLOSE = 'MENU_CLOSE';
|
||||||
|
|
||||||
|
// CATEGORIES
|
||||||
|
// actions that influence selected objects
|
||||||
|
export const CAT_SELECTION = 'SELECTION';
|
||||||
|
|
||||||
|
export function addObject(objectData) {
|
||||||
|
return { type: 'ADD_OBJECT', objectData };
|
||||||
|
}
|
||||||
|
export function d2DragStart(position, preDrags, objects, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: D2_DRAG_START, position, preDrags, objects, screenMatrixContainer, screenMatrixZoom };
|
||||||
|
}
|
||||||
|
export function d2Drag(position, previousPosition, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: D2_DRAG, position, previousPosition, screenMatrixContainer, screenMatrixZoom, log: false };
|
||||||
|
}
|
||||||
|
export function d2DragEnd(position, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: D2_DRAG_END, position, screenMatrixContainer, screenMatrixZoom };
|
||||||
|
}
|
||||||
|
export function d2SecondDragStart(position, preDrags, objects, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: D2_SECOND_DRAG_START, position, preDrags, objects, screenMatrixContainer, screenMatrixZoom };
|
||||||
|
}
|
||||||
|
export function d2SecondDrag(position, previousPosition, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return {
|
||||||
|
type: D2_SECOND_DRAG,
|
||||||
|
log: false,
|
||||||
|
position, previousPosition, screenMatrixContainer, screenMatrixZoom };
|
||||||
|
}
|
||||||
|
export function d2SecondDragEnd(position, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: D2_SECOND_DRAG_END, position, screenMatrixContainer, screenMatrixZoom };
|
||||||
|
}
|
||||||
|
export function d2Tap(position, objects, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: D2_TAP, position, objects, screenMatrixContainer, screenMatrixZoom };
|
||||||
|
}
|
||||||
|
export function d2MultitouchStart(positions, preDrags, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: D2_MULTITOUCH_START, positions, preDrags, screenMatrixContainer, screenMatrixZoom };
|
||||||
|
}
|
||||||
|
export function d2Multitouch(positions, previousPositions, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return {
|
||||||
|
log: false,
|
||||||
|
type: D2_MULTITOUCH,
|
||||||
|
positions, previousPositions, screenMatrixContainer, screenMatrixZoom
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function d2MultitouchEnd(positions, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: D2_MULTITOUCH_END, positions, screenMatrixContainer, screenMatrixZoom };
|
||||||
|
}
|
||||||
|
export function d2MouseWheel(position, wheelDelta, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: D2_MOUSE_WHEEL, position, wheelDelta, screenMatrixContainer, screenMatrixZoom, log: false };
|
||||||
|
}
|
||||||
|
export function d3DragStart(position, preDrags, objects) {
|
||||||
|
return { type: D3_DRAG_START, position, preDrags, objects };
|
||||||
|
}
|
||||||
|
export function d3Drag(position, previousPosition) {
|
||||||
|
return { type: D3_DRAG, position, previousPosition, log: false };
|
||||||
|
}
|
||||||
|
export function d3DragEnd(position) {
|
||||||
|
return { type: D3_DRAG_END, position };
|
||||||
|
}
|
||||||
|
export function d3SecondDragStart(position, preDrags, objects) {
|
||||||
|
return { type: D3_SECOND_DRAG_START, position, preDrags, objects };
|
||||||
|
}
|
||||||
|
export function d3SecondDrag(position, previousPosition) {
|
||||||
|
return { type: D3_SECOND_DRAG, log: false, position, previousPosition };
|
||||||
|
}
|
||||||
|
export function d3SecondDragEnd(position) {
|
||||||
|
return { type: D3_SECOND_DRAG_END, position };
|
||||||
|
}
|
||||||
|
export function d3Tap(position, objects) {
|
||||||
|
return { type: D3_TAP, position, objects };
|
||||||
|
}
|
||||||
|
export function d3MultitouchStart(positions, preDrags) {
|
||||||
|
return { type: D3_MULTITOUCH_START, positions, preDrags };
|
||||||
|
}
|
||||||
|
export function d3Multitouch(positions, previousPositions) {
|
||||||
|
return { log: false, type: D3_MULTITOUCH, positions, previousPositions };
|
||||||
|
}
|
||||||
|
export function d3MultitouchEnd(positions) {
|
||||||
|
return { type: D3_MULTITOUCH_END, positions };
|
||||||
|
}
|
||||||
|
export function d3MouseWheel(position, wheelDelta) {
|
||||||
|
return { type: D3_MOUSE_WHEEL, position, wheelDelta, log: false };
|
||||||
|
}
|
||||||
|
export function d2ChangeTool(tool) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({ type: D2_CHANGE_TOOL, tool });
|
||||||
|
|
||||||
|
const state = getState();
|
||||||
|
switch (tool) {
|
||||||
|
case d2Tools.PHOTO_GUIDE:
|
||||||
|
const hasImage = Object
|
||||||
|
.values(state.sketcher.present.objectsById)
|
||||||
|
.some(object => object.type === 'IMAGE_GUIDE');
|
||||||
|
if (!hasImage) dispatch(importImage());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case d2Tools.TEXT:
|
||||||
|
const hasText = Object
|
||||||
|
.values(state.sketcher.present.objectsById)
|
||||||
|
.some(object => object.type === 'TEXT');
|
||||||
|
if (!hasText) {
|
||||||
|
dispatch(d2textInit());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function transformStart(handle, position, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: TRANSFORM_START, handle, position, screenMatrixContainer, screenMatrixZoom };
|
||||||
|
}
|
||||||
|
export function transform(delta, position, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: TRANSFORM, delta, position, screenMatrixContainer, screenMatrixZoom, log: false };
|
||||||
|
}
|
||||||
|
export function transformEnd(screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
const state = getState();
|
||||||
|
|
||||||
|
if (state.sketcher.present.d2.transform.handle === 'dragselect') {
|
||||||
|
dispatch({ type: DRAG_SELECT, screenMatrixContainer, screenMatrixZoom, category: CAT_SELECTION });
|
||||||
|
}
|
||||||
|
dispatch({ type: TRANSFORM_END, screenMatrixContainer, screenMatrixZoom });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function multitouchTransformStart(screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: MULTITOUCH_TRANSFORM_START, screenMatrixContainer, screenMatrixZoom };
|
||||||
|
}
|
||||||
|
export function multitouchTransform(positions, previousPositions, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return {
|
||||||
|
type: MULTITOUCH_TRANSFORM, positions, previousPositions,
|
||||||
|
screenMatrixContainer, screenMatrixZoom, log: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function multitouchTransformEnd(screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return { type: MULTITOUCH_TRANSFORM_END, screenMatrixContainer, screenMatrixZoom };
|
||||||
|
}
|
||||||
|
export function d3ChangeTool(tool) {
|
||||||
|
return { type: D3_CHANGE_TOOL, tool };
|
||||||
|
}
|
||||||
|
export function contextChangeTool(tool) {
|
||||||
|
return { type: CONTEXT_CHANGE_TOOL, tool };
|
||||||
|
}
|
||||||
|
export function heightStart(handle) {
|
||||||
|
return { type: HEIGHT_START, handle };
|
||||||
|
}
|
||||||
|
export function height(delta) {
|
||||||
|
return { type: HEIGHT, delta, log: false };
|
||||||
|
}
|
||||||
|
export function heightEnd() {
|
||||||
|
return { type: HEIGHT_END };
|
||||||
|
}
|
||||||
|
export function twistStart() {
|
||||||
|
return { type: TWIST_START };
|
||||||
|
}
|
||||||
|
export function twist(delta) {
|
||||||
|
return { type: TWIST, delta, log: false };
|
||||||
|
}
|
||||||
|
export function twistEnd() {
|
||||||
|
return { type: TWIST_END };
|
||||||
|
}
|
||||||
|
export function sculptStart(heightIndex) {
|
||||||
|
return { type: SCULPT_START, heightIndex };
|
||||||
|
}
|
||||||
|
export function sculpt(delta) {
|
||||||
|
return { type: SCULPT, delta, log: false };
|
||||||
|
}
|
||||||
|
export function sculptEnd() {
|
||||||
|
return { type: SCULPT_END };
|
||||||
|
}
|
||||||
|
export function addSculptHandle(height, start) {
|
||||||
|
return { type: ADD_SCULPT_HANDLE, height, start };
|
||||||
|
}
|
||||||
|
export function removeSculptHandle(heightIndex) {
|
||||||
|
return { type: REMOVE_SCULPT_HANDLE, heightIndex };
|
||||||
|
}
|
||||||
|
export function stamp(hit) {
|
||||||
|
return { type: STAMP, hit };
|
||||||
|
}
|
||||||
|
export function clear() {
|
||||||
|
return { type: CLEAR };
|
||||||
|
}
|
||||||
|
export function select(shapeID) {
|
||||||
|
return { category: CAT_SELECTION, type: SELECT, shapeID };
|
||||||
|
}
|
||||||
|
export function deselect(shapeID) {
|
||||||
|
return { category: CAT_SELECTION, type: DESELECT, shapeID };
|
||||||
|
}
|
||||||
|
export function toggleSelect(shapeID) {
|
||||||
|
return { category: CAT_SELECTION, type: TOGGLE_SELECT, shapeID };
|
||||||
|
}
|
||||||
|
export function deselectAll() {
|
||||||
|
return { category: CAT_SELECTION, type: DESELECT_ALL };
|
||||||
|
}
|
||||||
|
export function selectAll() {
|
||||||
|
return { category: CAT_SELECTION, type: SELECT_ALL };
|
||||||
|
}
|
||||||
|
export function bedSelect() {
|
||||||
|
return { category: CAT_SELECTION, type: BED_SELECT };
|
||||||
|
}
|
||||||
|
export function deleteSelection() {
|
||||||
|
return { type: DELETE_SELECTION };
|
||||||
|
}
|
||||||
|
export function duplicateSelection() {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
// store current object ids so we can determine what objects are added by duplicate selection
|
||||||
|
const initialObjectIds = Object.keys(getState().sketcher.present.objectsById);
|
||||||
|
|
||||||
|
dispatch({ type: DUPLICATE_SELECTION });
|
||||||
|
|
||||||
|
const { selection, objectsById } = getState().sketcher.present;
|
||||||
|
// calculate object ids added by duplicate selection
|
||||||
|
const newIds = Object
|
||||||
|
.keys(objectsById)
|
||||||
|
.filter(id => !initialObjectIds.includes(id));
|
||||||
|
|
||||||
|
if (newIds.length === 0) return;
|
||||||
|
|
||||||
|
const selectedShapeDatas = selectionUtils.getSelectedObjectsSelector(selection.objects, objectsById);
|
||||||
|
const { center } = selectionUtils.getBoundingBox(selectedShapeDatas);
|
||||||
|
|
||||||
|
const ease = t => (Math.sin(((t + 0.5) * 2 * Math.PI) + (0.5 * Math.PI)) / 2) + 0.5;
|
||||||
|
newIds
|
||||||
|
.map(id => objectsById[id])
|
||||||
|
.forEach(shapeData => {
|
||||||
|
tween(300, t => {
|
||||||
|
t = ease(t);
|
||||||
|
|
||||||
|
const scale = t * 0.3 + 1.0;
|
||||||
|
const scaleMatrix = new Matrix().scaleAroundRelative(scale, scale, center);
|
||||||
|
const stepTransform = shapeData.transform.multiplyMatrix(scaleMatrix);
|
||||||
|
|
||||||
|
dispatch({ type: UPDATE_MATRIX, transform: stepTransform, id: shapeData.UID, log: false });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function tweenShape(id, duration, initialTransform, targetTransform, ease) {
|
||||||
|
return dispatch => {
|
||||||
|
const {
|
||||||
|
rotation: targetRotation,
|
||||||
|
position: targetPosition,
|
||||||
|
scale: targetScale
|
||||||
|
} = decomposeMatrix(targetTransform);
|
||||||
|
const {
|
||||||
|
rotation: initialRotation,
|
||||||
|
position: initialPosition,
|
||||||
|
scale: initialScale
|
||||||
|
} = decomposeMatrix(initialTransform);
|
||||||
|
|
||||||
|
return tween(duration, t => {
|
||||||
|
t = ease ? ease(t) : t;
|
||||||
|
const it = 1 - t;
|
||||||
|
|
||||||
|
const rotation = targetRotation * t + initialRotation * it;
|
||||||
|
const position = targetPosition.scale(t).add(initialPosition.scale(it));
|
||||||
|
const scale = targetScale.scale(t).add(initialScale.scale(it));
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: UPDATE_MATRIX,
|
||||||
|
transform: new Matrix({
|
||||||
|
x: position.x, y: position.y,
|
||||||
|
sx: scale.x, sy: scale.y,
|
||||||
|
rotation
|
||||||
|
}),
|
||||||
|
id,
|
||||||
|
log: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function union() {
|
||||||
|
return { type: UNION };
|
||||||
|
}
|
||||||
|
export function intersect() {
|
||||||
|
return { type: INTERSECT };
|
||||||
|
}
|
||||||
|
export function moveSelection(deltaX, deltaY) {
|
||||||
|
return { type: MOVE_SELECTION, deltaX, deltaY };
|
||||||
|
}
|
||||||
|
export function addImage(file) {
|
||||||
|
return (dispatch) => {
|
||||||
|
const url = URL.createObjectURL(file);
|
||||||
|
|
||||||
|
return dispatch({
|
||||||
|
type: ADD_IMAGE,
|
||||||
|
payload: loadImage(url).then(prepareImage)
|
||||||
|
}).then(() => {
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
dispatch({ type: D2_CHANGE_TOOL, tool: d2Tools.PHOTO_GUIDE });
|
||||||
|
}).catch(error => {
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
|
||||||
|
dispatch(notification.error({ position: 'tc', title: 'Error loading image, please try again with another image' }));
|
||||||
|
|
||||||
|
throw error; // rethrow for other listeners
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function d2textInit(position, textId, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return (dispatch) => {
|
||||||
|
dispatch({ type: D2_TEXT_INIT, position, textId, screenMatrixContainer, screenMatrixZoom });
|
||||||
|
dispatch(router.push('/sketch/inputtext'));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function d2textInputChange(text, family, weight, style, fill) {
|
||||||
|
return { type: D2_TEXT_INPUT_CHANGE, text, family, weight, style, fill };
|
||||||
|
}
|
||||||
|
export function d2textAdd() {
|
||||||
|
return { type: D2_TEXT_ADD };
|
||||||
|
}
|
||||||
|
|
||||||
|
const traceDragThrottle = createThrottle();
|
||||||
|
|
||||||
|
export function traceDrag(position, start, id, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({ type: TRACE_DRAG, position, start, id, screenMatrixContainer, screenMatrixZoom });
|
||||||
|
|
||||||
|
const state = getState();
|
||||||
|
|
||||||
|
traceDragThrottle(() => {
|
||||||
|
const { trace, activeShape } = state.sketcher.present.d2;
|
||||||
|
const shapeData = state.sketcher.present.objectsById[activeShape];
|
||||||
|
const tolerance = traceUtils.calculateTolerance(trace.start, trace.position);
|
||||||
|
const traceStart = calculatePointInImage(trace.start, shapeData, screenMatrixZoom);
|
||||||
|
|
||||||
|
if (tolerance > MAX_TRACE_TOLERANCE) return null;
|
||||||
|
|
||||||
|
return dispatch(floodFill(tolerance, shapeData, traceStart)).catch(() => {
|
||||||
|
// Ignore floodfill errors so throttle function doesn't get stuck
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function traceTap(position, objects, screenMatrixContainer, screenMatrixZoom) {
|
||||||
|
return async (dispatch, getState) => {
|
||||||
|
dispatch({ type: TRACE_TAP });
|
||||||
|
|
||||||
|
const state = getState();
|
||||||
|
const id = objects.find(_id => state.sketcher.present.objectsById[_id].type === 'IMAGE_GUIDE');
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
const shapeData = state.sketcher.present.objectsById[id];
|
||||||
|
const traceStart = calculatePointInImage(position, shapeData, screenMatrixZoom);
|
||||||
|
|
||||||
|
const { value: traceData } = await dispatch(floodFill(DEFAULT_TRACE_TOLERANCE, shapeData, traceStart));
|
||||||
|
|
||||||
|
return dispatch(traceFloodFill(traceData, shapeData));
|
||||||
|
} else {
|
||||||
|
return dispatch(importImage());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function importImage() {
|
||||||
|
return dispatch => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'file';
|
||||||
|
input.accept = 'image/*';
|
||||||
|
input.onchange = () => {
|
||||||
|
if (!input.files) return;
|
||||||
|
const [file] = Array.from(input.files);
|
||||||
|
if (!file) return;
|
||||||
|
dispatch(addImage(file)).then(() => {
|
||||||
|
delete window.importImageInput;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
input.click();
|
||||||
|
// Fixes import from camera work, see #935
|
||||||
|
window.importImageInput = input;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function traceDragEnd() {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
const state = getState();
|
||||||
|
|
||||||
|
dispatch({ type: TRACE_DRAG_END });
|
||||||
|
|
||||||
|
const id = state.sketcher.present.d2.activeShape;
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
const traceData = state.sketcher.present.d2.trace.floodFillData;
|
||||||
|
const shapeData = state.sketcher.present.objectsById[id];
|
||||||
|
|
||||||
|
return dispatch(traceFloodFill(traceData, shapeData));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function floodFill(tolerance, shapeData, start) {
|
||||||
|
return {
|
||||||
|
type: FLOOD_FILL,
|
||||||
|
payload: traceUtils.floodFill(tolerance, shapeData.imageData, start)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function traceFloodFill(traceData, shapeData) {
|
||||||
|
return {
|
||||||
|
type: TRACE_FLOOD_FILL,
|
||||||
|
payload: traceUtils.traceFloodFill(traceData, shapeData)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function menuOpen(menuValue) {
|
||||||
|
return { type: MENU_OPEN, menuValue };
|
||||||
|
}
|
||||||
|
export function menuClose(menuValue) {
|
||||||
|
return { type: MENU_CLOSE, menuValue };
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user