diff --git a/index.js b/index.js index 5895580..a98dd2f 100644 --- a/index.js +++ b/index.js @@ -29,11 +29,11 @@ window.actions = actionWrapper(actions, store.dispatch); // add inital shapes import * as CAL from 'cal'; store.dispatch(actions.addObject({ - type: 'STAR', - fill: true, + type: 'FREE_HAND', + fill: false, solid: false, - star: { innerRadius: 10, outerRadius: 20, rays: 5 }, - transform: new CAL.Matrix({ x: -20, y: 0 }) + 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', diff --git a/src/components/SketcherToolbars.js b/src/components/SketcherToolbars.js index c660bfc..cbd4217 100644 --- a/src/components/SketcherToolbars.js +++ b/src/components/SketcherToolbars.js @@ -171,7 +171,7 @@ function filterMenus(activeTool, numSelectedObjects, numFilledObjects, numSolidO return numSelectedObjects > 0; case contextTools.FILL_TOGGLE: - return numSelectedObjects > 0 && numSolidObjects === numSelectedObjects; + return numSelectedObjects > 0; case contextTools.ALIGN: return numSelectedObjects > 1; @@ -188,7 +188,7 @@ function filterMenus(activeTool, numSelectedObjects, numFilledObjects, numSolidO return activeTool === d2Tools.BRUSH; case contextTools.HOLE_TOGGLE: - return numSelectedObjects > 0 && numFilledObjects === numSelectedObjects; + return numSelectedObjects > 0; default: return true; diff --git a/src/d2/Shape.js b/src/d2/Shape.js index 8d50751..fe57e42 100644 --- a/src/d2/Shape.js +++ b/src/d2/Shape.js @@ -105,16 +105,8 @@ export default class Shape extends Matrix { const lineWidth = PIXEL_RATIO * LINE_WIDTH; context.globalAlpha = this.alpha; - if (!this._shapeData.solid) { - context.fillStyle = holePatern; - context.fill(); - - context.strokeStyle = 'black'; //'#888888'; - context.lineWidth = lineWidth / 2.0; - context.stroke(); - - } else if (this._shapeData.fill) { - context.fillStyle = this.color; + if (this._shapeData.fill) { + context.fillStyle = this._shapeData.solid ? this.color : holePatern; context.fill(); context.strokeStyle = 'black'; @@ -129,7 +121,7 @@ export default class Shape extends Matrix { context.stroke(); if (innerLineWidth > 0) { - context.strokeStyle = this.color; + context.strokeStyle = this._shapeData.solid ? this.color : holePatern; context.lineWidth = innerLineWidth; context.stroke(); } diff --git a/src/d3/ShapeMesh.js b/src/d3/ShapeMesh.js index d01e6be..018c746 100644 --- a/src/d3/ShapeMesh.js +++ b/src/d3/ShapeMesh.js @@ -45,7 +45,6 @@ class ShapeMesh extends THREE.Object3D { this._transform = transform; this._z = z; this._color = color; - this._fill = fill; this.updateSolid(solid, active); this.updatePoints(shapeData); } @@ -109,7 +108,7 @@ class ShapeMesh extends THREE.Object3D { updatePoints(shapeData) { if (this._shapeData && !shapeChanged(this._shapeData, shapeData)) return false; - this._fill = shapeData.fill; + this._fill = shapeData.fill || !shapeData.solid; this._points = shapeData.points; this._rectSize = shapeData.rectSize; this._circle = shapeData.circle; diff --git a/src/reducer/contextReducer.js b/src/reducer/contextReducer.js index 381232c..4e6f5b1 100644 --- a/src/reducer/contextReducer.js +++ b/src/reducer/contextReducer.js @@ -117,9 +117,9 @@ export default function (state, action) { return update(state, { objectsById: state.selection.objects.reduce((updateObject, { id }) => { - const { fill, type } = state.objectsById[id]; + const { type } = state.objectsById[id]; const d3Visible = SHAPE_TYPE_PROPERTIES[type].D3Visible; - if (fill && d3Visible) updateObject[id] = { solid: { $set: solid } }; + if (d3Visible) updateObject[id] = { solid: { $set: solid } }; return updateObject; }, {}) }); diff --git a/src/shape/shapeDataUtils.js b/src/shape/shapeDataUtils.js index a7e6274..ee1525d 100644 --- a/src/shape/shapeDataUtils.js +++ b/src/shape/shapeDataUtils.js @@ -15,10 +15,11 @@ export function shapeChanged(oldShapeData, newShapeData) { const textChanged = oldShapeData.text !== newShapeData.text; const polyPoints = oldShapeData.polyPoints !== newShapeData.polyPoints; const fillChanged = oldShapeData.fill !== newShapeData.fill; + const solidChanged = oldShapeData.solid !== newShapeData.solid; const heartChanged = oldShapeData.heart !== newShapeData.heart; return pointsChanged || holesChanged || rectSizeChanged || triangleSizeChanged || - circleChanged || starChanged || textChanged || polyPoints || fillChanged || heartChanged; + circleChanged || starChanged || textChanged || polyPoints || fillChanged || solidChanged || heartChanged; } export const getPointsBounds = memoize(getPointsBoundsRaw, { max: SHAPE_CACHE_LIMIT }); diff --git a/src/shape/shapeToPoints.js b/src/shape/shapeToPoints.js index 57eb6c9..46ae7f0 100644 --- a/src/shape/shapeToPoints.js +++ b/src/shape/shapeToPoints.js @@ -219,8 +219,43 @@ function shapeToPointsRaw(shapeData) { } export const shapeToPointsCornered = memoize(shapeToPointsCorneredRaw, { max: SHAPE_CACHE_LIMIT }); -function shapeToPointsCorneredRaw(shapeData) { - return shapeToPoints(shapeData).map(({ points: oldPoints, holes: oldHoles }) => { +function shapeToPointsCorneredRaw(shapeData, target) { + let shapes = shapeToPoints(shapeData); + + if (!shapeData.fill && !shapeData.solid) { + const newShapes = []; + for (const shape of shapes) { + const { points } = shape; + new ClipperShape([points], false, true, false, false) + .scaleUp(CLIPPER_PRECISION) + .round().removeDuplicates() + .offset(CLIPPER_PRECISION, { + jointType: 'jtSquare', + endType: 'etOpenSquare', + miterLimit: 2.0, + roundPrecision: 0.25 + }) + .scaleDown(CLIPPER_PRECISION) + .seperateShapes() + .forEach(shape => { + let [points, ...holes] = shape + .mapToLower() + .map(pathToVectorPath) + .map(path => { + path.push(path[0]); + return path; + }); + + points = setDirectionClockWise(points); + holes = holes.map(setDirectionCounterClockWise); + + newShapes.push({ points, holes }); + }); + } + shapes = newShapes; + } + + return shapes.map(({ points: oldPoints, holes: oldHoles }) => { const { path: points, map: pointsMap } = addCorners(oldPoints); const { paths: holes, maps: holesMaps } = oldHoles .map(hole => addCorners(hole))