mirror of
https://github.com/Doodle3D/Doodle3D-Core.git
synced 2024-12-22 11:03:48 +01:00
implement pipet
This commit is contained in:
parent
e1cd5c0260
commit
1021f5e8dc
14
index.js
14
index.js
@ -28,13 +28,13 @@ window.actions = actionWrapper(actions, store.dispatch);
|
||||
|
||||
// add inital shapes
|
||||
import * as CAL from 'cal';
|
||||
store.dispatch(actions.addObject({
|
||||
type: 'FREE_HAND',
|
||||
fill: false,
|
||||
solid: false,
|
||||
points: [new CAL.Vector(-20, 0), new CAL.Vector(10, 1)],
|
||||
transform: new CAL.Matrix({ x: 0, y: 0 })
|
||||
}));
|
||||
// store.dispatch(actions.addObject({
|
||||
// type: 'FREE_HAND',
|
||||
// fill: false,
|
||||
// solid: false,
|
||||
// points: [new CAL.Vector(-20, 0), new CAL.Vector(10, 1)],
|
||||
// transform: new CAL.Matrix({ x: 0, y: 0 })
|
||||
// }));
|
||||
store.dispatch(actions.addObject({
|
||||
type: 'RECT',
|
||||
fill: true,
|
||||
|
@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import * as CAL from 'cal';
|
||||
import * as toolNames from '../constants/d2Tools';
|
||||
import { PIPETTE } from '../constants/contextTools.js';
|
||||
import { CANVAS_SIZE } from '../constants/d2Constants';
|
||||
import createRAFOnce from '../utils/rafOnce.js';
|
||||
import Grid from '../d2/Grid.js';
|
||||
@ -13,6 +14,7 @@ import EraserTool from '../d2/tools/EraserTool.js';
|
||||
import BrushTool from '../d2/tools/BrushTool.js';
|
||||
import PolygonTool from '../d2/tools/PolygonTool.js';
|
||||
import CircleTool from '../d2/tools/CircleTool.js';
|
||||
import PipetteTool from '../d2/tools/PipetteTool.js';
|
||||
import TextTool from '../d2/tools/TextTool.js';
|
||||
import BucketTool from '../d2/tools/BucketTool.js';
|
||||
import PhotoGuideTool from '../d2/tools/PhotoGuideTool.js';
|
||||
@ -30,14 +32,15 @@ const CANVAS_WIDTH = CANVAS_SIZE * 2;
|
||||
const CANVAS_HEIGHT = CANVAS_SIZE * 2;
|
||||
|
||||
const tools = {
|
||||
[toolNames.TRANSFORM]: TransformTool,
|
||||
[toolNames.ERASER]: EraserTool,
|
||||
[toolNames.TEXT]: TextTool,
|
||||
[toolNames.BUCKET]: BucketTool,
|
||||
[toolNames.PHOTO_GUIDE]: PhotoGuideTool,
|
||||
[toolNames.BRUSH]: BrushTool,
|
||||
[toolNames.POLYGON]: PolygonTool,
|
||||
[toolNames.CIRCLE]: CircleTool
|
||||
[toolNames.TRANSFORM]: TransformTool,
|
||||
[toolNames.ERASER]: EraserTool,
|
||||
[toolNames.TEXT]: TextTool,
|
||||
[toolNames.BUCKET]: BucketTool,
|
||||
[toolNames.PHOTO_GUIDE]: PhotoGuideTool,
|
||||
[toolNames.BRUSH]: BrushTool,
|
||||
[toolNames.POLYGON]: PolygonTool,
|
||||
[toolNames.CIRCLE]: CircleTool,
|
||||
[PIPETTE]: PipetteTool
|
||||
};
|
||||
|
||||
// TODO the same as 3d
|
||||
|
@ -3,10 +3,12 @@ import PropTypes from 'prop-types';
|
||||
import Button from './Button.js';
|
||||
import Menu from './Menu.js';
|
||||
import bowser from 'bowser';
|
||||
import { connect } from 'react-redux';
|
||||
import { hexToStyle } from '../utils/colorUtils.js';
|
||||
// import createDebug from 'debug';
|
||||
// const debug = createDebug('d3d:ui:submenu');
|
||||
|
||||
export default class SubMenu extends React.Component {
|
||||
class SubMenu extends React.Component {
|
||||
static propTypes = {
|
||||
onSelect: PropTypes.func,
|
||||
onOpen: PropTypes.func,
|
||||
@ -64,12 +66,17 @@ export default class SubMenu extends React.Component {
|
||||
}
|
||||
};
|
||||
render() {
|
||||
const { id, value, selected, open, selectedValue, children, svg, toggleBehavior } = this.props;
|
||||
const { id, value, selected, open, selectedValue, children, svg, toggleBehavior, color, solid } = this.props;
|
||||
|
||||
const style = {};
|
||||
if (id === 'color-picker-tool') {
|
||||
style.fill = solid ? hexToStyle(color) : 'url(#holepattern)';
|
||||
}
|
||||
|
||||
let className = 'submenu';
|
||||
if (open) className += ' open';
|
||||
return (
|
||||
<li id={id} className={className} ref="li">
|
||||
<li id={id} className={className} ref="li" style={style}>
|
||||
<Button
|
||||
id={`${selectedValue}-menu`}
|
||||
value={selectedValue}
|
||||
@ -89,3 +96,8 @@ export default class SubMenu extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(state => ({
|
||||
color: state.sketcher.present.context.color,
|
||||
solid: state.sketcher.present.context.solid
|
||||
}))(SubMenu);
|
||||
|
@ -21,6 +21,7 @@ export const DARK_GREEN = 'color-dark-green';
|
||||
export const DARK_PINK = 'color-dark-pink';
|
||||
export const DARK_YELLOW = 'color-dark-yellow';
|
||||
export const HOLE_MATERIAL = 'color-hole-material';
|
||||
export const PIPETTE = 'pipette-tool';
|
||||
|
||||
export const COLORS = [
|
||||
LIGHT_BLUE,
|
||||
|
@ -5,6 +5,7 @@ export const TRANSFORM = 'transform-tool';
|
||||
export const ERASER = 'eraser-tool';
|
||||
export const TEXT = 'text-tool';
|
||||
export const PHOTO_GUIDE = 'photo-guide-tool';
|
||||
export const PIPETTE = 'pipette-tool';
|
||||
|
||||
export const CIRCLE = 'circle-tool';
|
||||
export const CIRCLE_SEGMENT = 'circle-segment-tool';
|
||||
|
@ -18,22 +18,3 @@ export const COLOR_STRING_TO_HEX = {
|
||||
[contextTools.DARK_PINK]: 0xe94481,
|
||||
[contextTools.DARK_YELLOW]: 0xdfde24
|
||||
};
|
||||
export const COLOR_HEX_TO_STRING = Object
|
||||
.entries(COLOR_STRING_TO_HEX)
|
||||
.reduce((obj, [key, value]) => {
|
||||
obj[value] = key;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
// LEGACY
|
||||
// add old color codes to corresponding color strings
|
||||
// so old doodles with old colors are previewd correctly in color picker color selector
|
||||
COLOR_HEX_TO_STRING[0x96cbef] = contextTools.BLUE;
|
||||
COLOR_HEX_TO_STRING[0x9bca87] = contextTools.GREEN;
|
||||
COLOR_HEX_TO_STRING[0xf08eb2] = contextTools.PINK;
|
||||
COLOR_HEX_TO_STRING[0xfff59a] = contextTools.YELLOW;
|
||||
COLOR_HEX_TO_STRING[0x7098b3] = contextTools.DARK_BLUE;
|
||||
COLOR_HEX_TO_STRING[0x7ab063] = contextTools.DARK_GREEN;
|
||||
COLOR_HEX_TO_STRING[0xb36984] = contextTools.DARK_PINK;
|
||||
COLOR_HEX_TO_STRING[0xf5e872] = contextTools.DARK_YELLOW;
|
||||
COLOR_HEX_TO_STRING[0x00DDFF] = contextTools.BLUE;
|
||||
|
@ -66,7 +66,7 @@ const context = {
|
||||
{ value: contextTools.LIGHT_GREEN, svg: '#color-picker-empty-fill' },
|
||||
{ value: contextTools.LIGHT_PINK, svg: '#color-picker-empty-fill' },
|
||||
{ value: contextTools.LIGHT_YELLOW, svg: '#color-picker-empty-fill' },
|
||||
// { value: contextTools.HOLE_MATERIAL, svg: '#color-picker-empty-fill' },
|
||||
{ value: contextTools.PIPETTE },
|
||||
{ value: contextTools.BLUE, svg: '#color-picker-empty-fill' },
|
||||
{ value: contextTools.GREEN, svg: '#color-picker-empty-fill' },
|
||||
{ value: contextTools.PINK, svg: '#color-picker-empty-fill' },
|
||||
|
8
src/d2/tools/PipetteTool.js
Normal file
8
src/d2/tools/PipetteTool.js
Normal file
@ -0,0 +1,8 @@
|
||||
import BaseTool from './BaseTool.js';
|
||||
|
||||
export default class PipetteTool extends BaseTool {
|
||||
constructor(dispatch, sceneSpaceContainer, renderRequest) {
|
||||
super(dispatch, sceneSpaceContainer, renderRequest);
|
||||
this.enableHitDetection = true;
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ import * as actions from '../actions/index.js';
|
||||
import { select } from './menusReducer.js';
|
||||
import { getSelectedObjectsSelector, getBoundingBox } from '../utils/selectionUtils.js';
|
||||
import { Matrix } from 'cal';
|
||||
import { updateTool as updateTool2d } from './d2/toolReducer.js';
|
||||
import { updateColor } from './selectionReducer.js';
|
||||
|
||||
export default function (state, action) {
|
||||
switch (action.category) {
|
||||
@ -16,15 +18,7 @@ export default function (state, action) {
|
||||
const [firstSelected] = state.selection.objects;
|
||||
const isSolid = firstSelected ? state.objectsById[firstSelected.id].solid : true;
|
||||
|
||||
let color;
|
||||
if (!isSolid) {
|
||||
color = contextTools.HOLE_MATERIAL;
|
||||
} else {
|
||||
const colorHex = firstSelected ? state.objectsById[firstSelected.id].color : state.context.color;
|
||||
// pick current draw color when color is unknown
|
||||
color = COLOR_HEX_TO_STRING[colorHex] || COLOR_HEX_TO_STRING[state.context.color];
|
||||
}
|
||||
|
||||
const color = isSolid ? contextTools.PIPETTE : contextTools.HOLE_MATERIAL;
|
||||
menus = select(menus, color);
|
||||
|
||||
const fillBool = firstSelected && state.objectsById[firstSelected.id].fill;
|
||||
@ -40,7 +34,8 @@ export default function (state, action) {
|
||||
|
||||
switch (action.type) {
|
||||
case actions.D2_CHANGE_TOOL: {
|
||||
const color = state.context.solid ? COLOR_HEX_TO_STRING[state.context.color] : contextTools.HOLE_MATERIAL;
|
||||
const color = state.context.solid ? contextTools.PIPETTE : contextTools.HOLE_MATERIAL;
|
||||
|
||||
return update(state, {
|
||||
menus: { $set: select(state.menus, color) }
|
||||
});
|
||||
@ -51,6 +46,17 @@ export default function (state, action) {
|
||||
}
|
||||
|
||||
switch (action.tool) {
|
||||
case contextTools.PIPETTE: {
|
||||
state = update(state, {
|
||||
context: {
|
||||
lastTool: { $set: state.d2.tool }
|
||||
}
|
||||
});
|
||||
state = updateTool2d(state, contextTools.PIPETTE);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
case contextTools.HOLE_MATERIAL: {
|
||||
return update(state, {
|
||||
objectsById: state.selection.objects.reduce((updateObject, { id }) => {
|
||||
@ -76,19 +82,7 @@ export default function (state, action) {
|
||||
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 },
|
||||
solid: { $set: true }
|
||||
};
|
||||
return updateObject;
|
||||
}, {}),
|
||||
context: {
|
||||
solid: { $set: true },
|
||||
color: { $set: color }
|
||||
}
|
||||
});
|
||||
return updateColor(state, color);
|
||||
}
|
||||
|
||||
case contextTools.ERASER_SIZE_SMALL:
|
||||
|
@ -12,8 +12,10 @@ import textReducer from './tools/textReducer.js';
|
||||
import photoGuideReducer from './tools/photoGuideReducer.js';
|
||||
import { transformReducer } from './tools/transformReducer.js';
|
||||
import eraserReducer from './tools/eraserReducer.js';
|
||||
import pipetteReducer from './tools/pipetteReducer.js';
|
||||
import * as actions from '../../actions/index.js';
|
||||
import * as tools from '../../constants/d2Tools.js';
|
||||
import { PIPETTE } from '../../constants/contextTools.js';
|
||||
import createDebug from 'debug';
|
||||
const debug = createDebug('d3d:reducer:d2:tool');
|
||||
|
||||
@ -32,7 +34,8 @@ const reducers = {
|
||||
[tools.PHOTO_GUIDE]: photoGuideReducer,
|
||||
[tools.BUCKET]: bucketReducer,
|
||||
[tools.TEXT]: textReducer,
|
||||
[tools.BRUSH]: penReducer
|
||||
[tools.BRUSH]: penReducer,
|
||||
[PIPETTE]: pipetteReducer
|
||||
};
|
||||
|
||||
export default function toolReducer(state, action) {
|
||||
@ -56,7 +59,7 @@ export default function toolReducer(state, action) {
|
||||
}
|
||||
}
|
||||
|
||||
function updateTool(state, newTool) {
|
||||
export function updateTool(state, newTool) {
|
||||
if (newTool === state.d2.tool) {
|
||||
return state;
|
||||
} else {
|
||||
|
@ -8,7 +8,6 @@ import { shapeToPoints } from '../../../shape/shapeToPoints.js';
|
||||
import { applyMatrixOnShape, pathToVectorPath } from '../../../utils/vectorUtils.js';
|
||||
import { addObject } from '../../../reducer/objectReducers.js';
|
||||
import subtractShapeFromState from '../../../utils/subtractShapeFromState.js';
|
||||
import { getColor, getFirst, filterType, getObjectsFromIds } from '../../../utils/objectSelectors.js';
|
||||
import createDebug from 'debug';
|
||||
const debug = createDebug('d3d:reducer:bucket');
|
||||
|
||||
@ -20,19 +19,6 @@ export default function bucketReducer(state, action) {
|
||||
switch (action.type) {
|
||||
case actions.D2_TAP:
|
||||
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 => (
|
||||
|
21
src/reducer/d2/tools/pipetteReducer.js
Normal file
21
src/reducer/d2/tools/pipetteReducer.js
Normal file
@ -0,0 +1,21 @@
|
||||
import { updateColor } from '../../selectionReducer.js';
|
||||
import { getColor } from '../../../utils/objectSelectors.js';
|
||||
import { select } from '../../menusReducer.js';
|
||||
import update from 'react-addons-update';
|
||||
import { updateTool as updateTool2d } from '../toolReducer.js';
|
||||
|
||||
export default function pipetteReducer(state, action) {
|
||||
const [object] = action.objects;
|
||||
if (object) {
|
||||
const shapeData = state.objectsById[object];
|
||||
let color;
|
||||
if (shapeData.type === 'IMAGE_GUIDE') {
|
||||
color = getColor(shapeData, action.position, action.screenMatrixZoom);
|
||||
} else {
|
||||
color = shapeData.color;
|
||||
}
|
||||
state = updateColor(state, color);
|
||||
}
|
||||
state = updateTool2d(state, state.context.lastTool);
|
||||
return state;
|
||||
}
|
@ -131,3 +131,19 @@ function deselectAll(state) {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function updateColor(state, color) {
|
||||
return update(state, {
|
||||
objectsById: state.selection.objects.reduce((updateObject, { id }) => {
|
||||
updateObject[id] = {
|
||||
color: { $set: color },
|
||||
solid: { $set: true }
|
||||
};
|
||||
return updateObject;
|
||||
}, {}),
|
||||
context: {
|
||||
solid: { $set: true },
|
||||
color: { $set: color }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -257,45 +257,49 @@
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#color-light-blue, #color-light-blue-menu {
|
||||
#color-light-blue {
|
||||
fill: #c8e4f7;
|
||||
}
|
||||
#color-light-green, #color-light-green-menu {
|
||||
#color-light-green {
|
||||
fill: #cbe6c0;
|
||||
}
|
||||
#color-light-pink, #color-light-pink-menu {
|
||||
#color-light-pink {
|
||||
fill: #f8c4d8;
|
||||
}
|
||||
#color-light-yellow, #color-light-yellow-menu {
|
||||
#color-light-yellow {
|
||||
fill: #f5f5c0;
|
||||
}
|
||||
#color-blue, #color-blue-menu {
|
||||
#color-blue {
|
||||
fill: #92c8ef;
|
||||
}
|
||||
#color-green, #color-green-menu {
|
||||
#color-green {
|
||||
fill: #99cc81;
|
||||
}
|
||||
#color-pink, #color-pink-menu {
|
||||
#color-pink {
|
||||
fill: #f28bb1;
|
||||
}
|
||||
#color-yellow, #color-yellow-menu {
|
||||
#color-yellow {
|
||||
fill: #ebea7f;
|
||||
}
|
||||
#color-dark-blue, #color-dark-blue-menu {
|
||||
#color-dark-blue {
|
||||
fill: #50a8e4;
|
||||
}
|
||||
#color-dark-green, #color-dark-green-menu {
|
||||
#color-dark-green {
|
||||
fill: #5aae31;
|
||||
}
|
||||
#color-dark-pink, #color-dark-pink-menu {
|
||||
#color-dark-pink {
|
||||
fill: #e94481;
|
||||
}
|
||||
#color-dark-yellow, #color-dark-yellow-menu {
|
||||
#color-dark-yellow {
|
||||
fill: #dfde24;
|
||||
}
|
||||
#color-hole-material, #color-hole-material-menu {
|
||||
#color-hole-material {
|
||||
fill: url(#holepattern);
|
||||
}
|
||||
#pipette-tool {
|
||||
background-size: 30px;
|
||||
background-image: url('../img/contextmenu/btnPicker.png');
|
||||
}
|
||||
|
||||
/* menu's */
|
||||
.menu {
|
||||
|
Loading…
Reference in New Issue
Block a user