fix imports

This commit is contained in:
casperlamboo 2017-11-14 16:01:04 +01:00
parent 08e88805c4
commit 20995d0ac7
9 changed files with 502 additions and 29 deletions

View File

@ -0,0 +1,177 @@
import update from 'react-addons-update';
import * as contextTools from 'src/js/constants/contextTools.js';
import { COLOR_STRING_TO_HEX, COLOR_HEX_TO_STRING } from 'src/js/constants/general.js';
import { ERASER_SIZES, BRUSH_SIZES } from 'src/js/constants/d2Constants.js';
import * as actions from 'src/js/actions/index.js';
import { select } from './menusReducer.js';
import { getSelectedObjectsSelector, getBoundingBox } from 'src/js/utils/selectionUtils.js';
import { Matrix } from 'cal';
export default function (state, action) {
switch (action.category) {
case actions.sketcher.CAT_SELECTION: {
let menus = state.menus;
const [firstSelected] = state.selection.objects;
const colorHex = firstSelected ? state.objectsById[firstSelected.id].color : state.context.color;
// pick current draw color when color is unknown
const color = COLOR_HEX_TO_STRING[colorHex] || COLOR_HEX_TO_STRING[state.context.color];
menus = select(menus, color);
const fillBool = firstSelected && state.objectsById[firstSelected.id].fill;
const fill = fillBool ? contextTools.FILL_TOGGLE_FILL : contextTools.FILL_TOGGLE_OUTLINE;
menus = select(menus, fill);
return update(state, { menus: { $set: menus } });
}
default:
break;
}
switch (action.type) {
case actions.sketcher.D2_CHANGE_TOOL: {
const color = COLOR_HEX_TO_STRING[state.context.color];
return update(state, {
menus: { $set: select(state.menus, color) }
});
}
default:
break;
}
switch (action.tool) {
case contextTools.LIGHT_BLUE:
case contextTools.LIGHT_GREEN:
case contextTools.LIGHT_PINK:
case contextTools.LIGHT_YELLOW:
case contextTools.BLUE:
case contextTools.GREEN:
case contextTools.PINK:
case contextTools.YELLOW:
case contextTools.DARK_BLUE:
case contextTools.DARK_GREEN:
case contextTools.DARK_PINK:
case contextTools.DARK_YELLOW: {
const color = COLOR_STRING_TO_HEX[action.tool];
return update(state, {
objectsById: state.selection.objects.reduce((updateObject, { id }) => {
updateObject[id] = { color: { $set: color } };
return updateObject;
}, {}),
context: {
color: { $set: color }
}
});
}
case contextTools.ERASER_SIZE_SMALL:
case contextTools.ERASER_SIZE_MEDIUM:
case contextTools.ERASER_SIZE_LARGE: {
const size = ERASER_SIZES[action.tool];
return update(state, {
d2: {
eraser: {
size: { $set: size }
}
}
});
}
case contextTools.BRUSH_SIZE_SMALL:
case contextTools.BRUSH_SIZE_MEDIUM:
case contextTools.BRUSH_SIZE_LARGE: {
const size = BRUSH_SIZES[action.tool];
return update(state, {
d2: {
brush: {
size: { $set: size }
}
}
});
}
case contextTools.FILL_TOGGLE_FILL:
case contextTools.FILL_TOGGLE_OUTLINE: {
const fill = action.tool === contextTools.FILL_TOGGLE_FILL;
return update(state, {
objectsById: state.selection.objects.reduce((updateObject, { id }) => {
updateObject[id] = { fill: { $set: fill } };
return updateObject;
}, {})
});
}
case contextTools.ALIGN_LEFT:
case contextTools.ALIGN_HORIZONTAL:
case contextTools.ALIGN_RIGHT:
case contextTools.ALIGN_TOP:
case contextTools.ALIGN_VERTICAL:
case contextTools.ALIGN_BOTTOM: {
if (state.selection.objects < 2) return state;
const selection = state.selection;
const selectedShapeDatas = getSelectedObjectsSelector(selection.objects, state.objectsById);
const totalBoundingBox = getBoundingBox(selectedShapeDatas);
for (const shapeData of selectedShapeDatas) {
const boundingBox = getBoundingBox([shapeData]);
let deltaX = 0;
let deltaY = 0;
switch (action.tool) {
case contextTools.ALIGN_LEFT:
deltaX = totalBoundingBox.min.x - boundingBox.min.x;
break;
case contextTools.ALIGN_HORIZONTAL:
deltaX = totalBoundingBox.center.x - boundingBox.center.x;
break;
case contextTools.ALIGN_RIGHT:
deltaX = totalBoundingBox.max.x - boundingBox.max.x;
break;
case contextTools.ALIGN_TOP:
deltaY = totalBoundingBox.min.z - boundingBox.min.z;
break;
case contextTools.ALIGN_VERTICAL:
deltaY = totalBoundingBox.center.y - boundingBox.center.y;
break;
case contextTools.ALIGN_BOTTOM:
deltaY = totalBoundingBox.max.z - boundingBox.max.z;
break;
default:
break;
}
const transform = state.objectsById[shapeData.UID].transform.translate(deltaX, deltaY);
state = update(state, {
objectsById: {
[shapeData.UID]: {
transform: { $set: transform }
}
},
selection: {
objects: {
[selection.objects.findIndex(({ id }) => id === shapeData.UID)]: {
initialTransform: { $set: transform }
}
}
}
});
}
state = update(state, {
selection: {
transform: { $set: new Matrix() }
}
});
return state;
}
default:
return state;
}
}

View File

@ -1,16 +1,14 @@
import update from 'react-addons-update';
import fillPath from 'fill-path';
import ClipperShape from 'clipper-js';
import * as actions from '../../../actions/index.js';
import { SHAPE_TYPE_PROPERTIES } from '../../../constants/shapeTypeProperties.js';
import { LINE_WIDTH, CLIPPER_PRECISION } from '../../../constants/d2Constants.js';
import createDebug from 'debug';
import { shapeToPoints, applyMatrixOnShape, pathToVectorPath } from '../../../utils/shapeDataUtils.js';
import { shapeToPoints, applyMatrixOnShape, pathToVectorPath } from '../../../shape/shapeDataUtils.js';
import { addObject } from '../../../reducers/objectReducers.js';
import fillPath from 'fill-path';
import ClipperShape from 'clipper-js';
import subtractShapeFromState from '../../../utils/subtractShapeFromState.js';
import update from 'react-addons-update';
import { get as getConfig } from '../../../services/config.js';
import { getColor, getFirst, filterType, getObjectsFromIds } from '../../../utils/objectSelectors.js';
import createDebug from 'debug';
const debug = createDebug('d3d:reducer:bucket');
const MITER_LIMIT = 30.0;
@ -20,22 +18,20 @@ export default function bucketReducer(state, action) {
switch (action.type) {
case actions.D2_TAP:
const { experimentalColorPicker } = getConfig();
let color = state.context.color;
if (experimentalColorPicker) {
const imageColor = getColor(
getFirst(
filterType(
getObjectsFromIds(state, action.objects),
'IMAGE_GUIDE'
)
),
action.position,
action.screenMatrixZoom
);
if (imageColor !== null) color = imageColor;
}
const color = state.context.color;
// if (experimentalColorPicker) {
// const imageColor = getColor(
// getFirst(
// filterType(
// getObjectsFromIds(state, action.objects),
// 'IMAGE_GUIDE'
// )
// ),
// action.position,
// action.screenMatrixZoom
// );
// if (imageColor !== null) color = imageColor;
// }
// if clicked on a filled shape change shape color
const filledPathIndex = action.objects.findIndex(id => (

View File

@ -1,8 +1,8 @@
import update from 'react-addons-update';
import { Utils } from 'cal';
import * as THREE from 'three';
import { SHAPE_TYPE_PROPERTIES } from '../../../constatants/shapeTypeProperties.js';
import * as d3Tools from '../../../constatants/d3Tools.js';
import { SHAPE_TYPE_PROPERTIES } from '../../../constants/shapeTypeProperties.js';
import * as d3Tools from '../../../constants/d3Tools.js';
import { getSelectedObjectsSelector, getBoundingBox } from '../../../utils/selectionUtils.js';
import * as actions from '../../../actions/index.js';
// import createDebug from 'debug';

View File

@ -1,7 +1,7 @@
import * as actions from '../../actions/index.js';
import * as actions from '../../../actions/index.js';
import { addObject, addSpaceActive } from '../../objectReducers.js';
import { recursiveClone } from '../../utils/clone.js';
import { getBoundingBox, getSelectedObjectsSelector } from '../../utils/selectionUtils.js';
import { recursiveClone } from '../../../utils/clone.js';
import { getBoundingBox, getSelectedObjectsSelector } from '../../../utils/selectionUtils.js';
import { updateInitTransform } from '../../d2/tools/transformReducer.js';
import update from 'react-addons-update';
import * as THREE from 'three';

View File

@ -0,0 +1,97 @@
import * as actions from 'src/js/actions/index.js';
import * as d2Tools from 'src/js/constants/d2Tools.js';
import initialMenuStructure from 'src/js/constants/menu.js';
// import createDebug from 'debug';
// const debug = createDebug('d3d:reducer:menu:index');
// flatten & add menu structure
const initialState = addChildren({}, initialMenuStructure);
// read children recursivly and add them flat/unnested to the state
function addChildren(state, childrenData) {
return childrenData.reduce((reducedState, childData) => {
reducedState = addItem(reducedState, childData);
if (childData.children) {
reducedState = addChildren(reducedState, childData.children);
}
return reducedState;
}, { ...state });
}
function addItem(state, data) {
state[data.value] = {
disabled: false,
selected: '',
open: false,
...data, // override defaults with given data
children: getChildrenValues(data.children)
};
return state;
}
function getChildrenValues(childrenData = []) {
return childrenData.map(child => child.value);
}
// item specific reducer
function item(state, action) {
switch (action.type) {
case actions.sketcher.MENU_OPEN:
case actions.sketcher.MENU_CLOSE:
return {
...state,
open: (action.type === actions.sketcher.MENU_OPEN)
};
default:
return state;
}
}
function getMenu(state, targetValue) {
if (state[targetValue] === undefined) {
throw new Error(`Can't find menu item '${targetValue}'`);
}
for (const value in state) {
if (state[value].children.indexOf(targetValue) !== -1) {
return value;
}
}
return null;
}
export const select = (state, value) => {
const menuValue = getMenu(state, value);
// debug(`selectItem: ${value} in ${menuValue}`);
if (menuValue === null) return state;
// select value in menu
state = {
...state,
[menuValue]: {
...state[menuValue],
selected: value
}
};
// try selecting menu in it's menu
state = select(state, menuValue);
return state;
};
export default function menusReducer(state = initialState, action) {
if (action.category === actions.sketcher.CAT_SELECTION) {
state = select(state, d2Tools.TRANSFORM);
}
switch (action.type) {
case actions.sketcher.MENU_OPEN:
case actions.sketcher.MENU_CLOSE:
if (action.menuValue === undefined) return state;
return {
...state,
[action.menuValue]: item(state[action.menuValue], action)
};
case actions.sketcher.D2_CHANGE_TOOL:
case actions.sketcher.D3_CHANGE_TOOL:
case actions.sketcher.CONTEXT_CHANGE_TOOL:
// recursivly select items in menu's
return select(state, action.tool);
default:
return state;
}
}

View File

@ -0,0 +1,136 @@
import R from 'ramda';
// import createDebug from 'debug';
// const debug = createDebug('d3d:reducers:points');
export function mergePaths(pathA, pathB, matchIndexes) {
if (matchIndexes[0] !== -1) { // if first path's first point matches
// always reverse first path
const sortedA = R.reverse(pathA);
// if matches with second path's second point reverse
const sortedB = (matchIndexes[0] === 1) ? R.reverse(pathB) : pathB;
// add b behind a, removing overlapping point
return sortedA.concat(sortedB.slice(1));
} else if (matchIndexes[1] !== -1) { // if first path's second point matches
// no need to reorder first path
const sortedA = pathA;
// if matches with second path's second point reverse
const sortedB = (matchIndexes[1] === 1) ? R.reverse(pathB) : pathB;
// add b behind a, removing overlapping point
return sortedA.concat(sortedB.slice(1));
} else {
return null;
}
}
// get just the end points of a path
export const getEndPoints = R.juxt([R.head, R.last]);
export const getEndPointPaths = R.map(getEndPoints);
const vectorEquals = R.curry(
(a, b) => a.equals(b)
);
// find the index of a point in an array of points
export const findPointIndex = R.curry(
(points, point) => R.findIndex(vectorEquals(point), points)
);
export const findEndPointIndex = R.curry(
(points, point) => findPointIndex(getEndPoints(points), point)
);
// find indexes of multiple points in array of points,
// returned as array of indexes
// Result examples:
// [0]: a's first point matches b's first point
// [1]: a's first point matches b's second point
// [-1]: a's first point matches none of b's points
// [1, 0]: a's first point matches and b's second point and a's second point matches b's first point
export const findPointsIndexes = R.curry(
(pointsA, pointsB) => R.map(findPointIndex(pointsB), pointsA)
);
export const findEndPointsIndexes = R.curry(
(pathA, pathB) => findPointsIndexes(
getEndPoints(pathA),
getEndPoints(pathB)
)
);
// find the index of a point in an array of paths
// (paths are arrays of points)
// returns first result
// returns array with
// - index of path with matching point
// - matching index (see findPointsIndexes)
export function findPointIndexInPaths(point, paths) {
// debug('findPointIndexInPaths: ', toString(point), toString(paths));
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
// find matching endpoints
const index = findPointIndex(path, point);
// debug(` ${i}: index: `, index);
// if found stop searching
if (index > -1) return [i, index];
}
return null;
}
export const findEndPointIndexInPaths = R.curry(
(point, paths) => findPointIndexInPaths(point, getEndPointPaths(paths))
);
// find indexes of matching points of path inside other path
// returns first result
// returns array with
// - index of path with matching point
// - array of matching indexes (see findPointsIndexes)
export function findPointsIndexesOfPathInPaths(paths, path) {
// console.log('findPointsIndexesOfPathInPaths');
// console.log(' paths: ', toString(paths));
// console.log(' path: ', toString(path));
for (let i = 0; i < paths.length; i++) {
const otherPath = paths[i];
// skip current path
if (otherPath === path) continue;
// find matching endpoints
const indexes = findPointsIndexes(path, otherPath);
// console.log(` ${i}: indexes: `, indexes);
// found any matching indexes?
// indexes contains any item that's larget than -1
const foundMatch = R.any(R.lt(-1))(indexes);
// if found stop searching
// return index of matching path and indexes of machting end points
if (foundMatch) return [i, indexes];
}
return null;
}
// find indexes of matching end points of path inside other path
// see: findPointsIndexesOfPathInPaths
export function findEndPointsIndexesOfPathInPaths(paths, path) {
return findPointsIndexesOfPathInPaths(
R.map(getEndPoints, paths),
getEndPoints(path)
);
}
// cross-compare points of multiple paths
// returns first match
// array with
// - index of path A with matching point
// - index of path B with matching point
// - array of matching indexes (see findPointsIndexes)
export function findPointIndexesOfPaths(paths) {
// console.log('findPointIndexesOfPaths');
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
const indexes = findPointsIndexesOfPathInPaths(paths, path);
// console.log(' indexes: ', toString(indexes));
if (indexes !== null) return [i, ...indexes];
}
return null;
}
// cross-compare endpoints of multiple paths
export function findEndPointIndexesOfPaths(paths) {
return findPointIndexesOfPaths(R.map(getEndPoints, paths));
}

View File

@ -1,7 +1,7 @@
import update from 'react-addons-update';
import * as actions from '../actions/index.js';
import { Vector } from 'cal';
import { shapeToPoints } from '../utils/shapeDataUtils.js';
import { shapeToPoints } from '../shape/shapeDataUtils.js';
import createDebug from 'debug';
const debug = createDebug('d3d:reducer:selection');

View File

@ -0,0 +1,67 @@
import { SHAPE_TYPE_PROPERTIES } from 'src/js/constants/shapeTypeProperties.js';
import { calculatePointInImage } from 'src/js/utils/matrixUtils.js';
import R from 'ramda';
// import createDebug from 'debug';
// const debug = createDebug('d3d:utils:objectSelectors');
// returns true if object is a closed shape
export function closedShapesFilter({ points }) {
return points[0].equals(points[points.length - 1]);
}
// returns true if object is a open (not closed) shape
export function openShapesFilter(object) {
return !closedShapesFilter(object);
}
// returns true if object should snap
export function snappingFilter({ type }) {
return SHAPE_TYPE_PROPERTIES[type].snapping;
}
export function getObjectsById(state) {
return state.sketcher.present.objectsById;
}
export function contains(state, testFn) {
const objects = R.values(getObjectsById(state));
const index = R.findIndex(testFn, objects);
return (index !== -1);
}
export function containsType(state, type) {
return contains(state, R.propEq('type', type));
}
export function getSnappingPoints(state, matrix) {
return Object.values(state.objectsById)
.filter(snappingFilter) // filter closed shapes
.filter(openShapesFilter)
.map(shapeData => {
const transform = matrix ? shapeData.transform.multiplyMatrix(matrix) : shapeData.transform;
const startPoint = shapeData.points[0].applyMatrix(transform);
const endPoint = shapeData.points[shapeData.points.length - 1].applyMatrix(transform);
return { shapeData, startPoint, endPoint };
});
}
export function getObjectsFromIds(state, ids) {
return ids.map(id => state.objectsById[id]);
}
export function filterType(objects, type) {
return objects.filter(value => value.type === type);
}
export function getFirst(objects) {
return objects.length > 0 ? objects[0] : null;
}
export function getColor(shapeData, position, screenMatrixZoom) {
if (!shapeData) return null;
const canvas = shapeData.imageData;
const context = canvas.getContext('2d');
const start = calculatePointInImage(position, shapeData, screenMatrixZoom);
const [r, g, b] = context.getImageData(start.x, start.y, 1, 1).data;
const color = (r << 16) + (g << 8) + b;
return color;
}