Skip to content

Commit 75f07b4

Browse files
authored
Merge pull request #5 from biglyderv/develop
Add stars to triangle mode, fix non-integers in triangle mode
2 parents 8e98e64 + f475331 commit 75f07b4

File tree

5 files changed

+121
-39
lines changed

5 files changed

+121
-39
lines changed

src/components/mode-tools/mode-tools.jsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import layout from '../../lib/layout-constants';
1111
import { changeBrushSize, changeSegSize } from '../../reducers/brush-mode';
1212
import { changeBrushSize as changeEraserSize } from '../../reducers/eraser-mode';
1313
import { changeRoundedCornerSize } from '../../reducers/rounded-rect-mode';
14-
import { changeTrianglePolyCount } from '../../reducers/triangle-mode';
14+
import { changeTrianglePolyCount, changeTrianglePointCount } from '../../reducers/triangle-mode';
1515
import { changeCurrentlySelectedShape } from '../../reducers/sussy-mode';
1616
import { changeBitBrushSize } from '../../reducers/bit-brush-size';
1717
import { changeBitEraserSize } from '../../reducers/bit-eraser-size';
@@ -270,6 +270,8 @@ const ModeToolsComponent = props => {
270270
const currentIcon = triangleIcon;
271271
const currentSideValue = props.trianglePolyValue;
272272
const changeFunction = props.onPolyCountSliderChange;
273+
const currentPointValue = props.trianglePointValue;
274+
const changeFunctionPoint = props.onPointCountSliderChange;
273275
return (
274276
<div className={classNames(props.className, styles.modeTools)}>
275277
<div>
@@ -289,6 +291,15 @@ const ModeToolsComponent = props => {
289291
value={currentSideValue}
290292
onSubmit={changeFunction}
291293
/>
294+
<LiveInput
295+
range
296+
small
297+
max={1000}
298+
min="1"
299+
type="number"
300+
value={currentPointValue}
301+
onSubmit={changeFunctionPoint}
302+
/>
292303
</div>
293304
);
294305
}
@@ -706,6 +717,7 @@ ModeToolsComponent.propTypes = {
706717
eraserValue: PropTypes.number,
707718
roundedCornerValue: PropTypes.number,
708719
trianglePolyValue: PropTypes.number,
720+
trianglePointValue: PropTypes.number,
709721
currentlySelectedShape: PropTypes.string,
710722
fillBitmapShapes: PropTypes.bool,
711723
format: PropTypes.oneOf(Object.keys(Formats)),
@@ -753,6 +765,7 @@ const mapStateToProps = state => ({
753765
eraserValue: state.scratchPaint.eraserMode.brushSize,
754766
roundedCornerValue: state.scratchPaint.roundedRectMode.roundedCornerSize,
755767
trianglePolyValue: state.scratchPaint.triangleMode.trianglePolyCount,
768+
trianglePointValue: state.scratchPaint.triangleMode.trianglePointCount,
756769
currentlySelectedShape: state.scratchPaint.sussyMode.currentlySelectedShape
757770
});
758771
const mapDispatchToProps = dispatch => ({
@@ -768,6 +781,9 @@ const mapDispatchToProps = dispatch => ({
768781
onPolyCountSliderChange: polyCount => {
769782
dispatch(changeTrianglePolyCount(polyCount));
770783
},
784+
onPointCountSliderChange: polyCount => {
785+
dispatch(changeTrianglePointCount(polyCount));
786+
},
771787
onCurrentlySelectedShapeChange: shape => {
772788
dispatch(changeCurrentlySelectedShape(shape));
773789
},

src/helper/selection-tools/reshape-tool.js

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import log from '../../log/log';
33
import keyMirror from 'keymirror';
44

55
import Modes from '../../lib/modes';
6-
import {isBoundsItem} from '../item';
7-
import {hoverBounds, hoverItem} from '../guides';
8-
import {sortItemsByZIndex} from '../math';
9-
import {getSelectedLeafItems, getSelectedSegments} from '../selection';
6+
import { isBoundsItem } from '../item';
7+
import { hoverBounds, hoverItem } from '../guides';
8+
import { sortItemsByZIndex } from '../math';
9+
import { getSelectedLeafItems, getSelectedSegments } from '../selection';
1010
import MoveTool from './move-tool';
1111
import PointTool from './point-tool';
1212
import HandleTool from './handle-tool';
@@ -32,23 +32,23 @@ const ReshapeModes = keyMirror({
3232
*/
3333
class ReshapeTool extends paper.Tool {
3434
/** Distance within which mouse is considered to be hitting an item */
35-
static get TOLERANCE () {
35+
static get TOLERANCE() {
3636
return ReshapeTool.HANDLE_RADIUS + ReshapeTool.HANDLE_PADDING;
3737
}
3838
/**
3939
* Units of padding around the visible handle area that will still register clicks as "touching the handle"
4040
*/
41-
static get HANDLE_PADDING () {
41+
static get HANDLE_PADDING() {
4242
return 1;
4343
}
4444
/**
4545
* Handles' radius, including the stroke
4646
*/
47-
static get HANDLE_RADIUS () {
47+
static get HANDLE_RADIUS() {
4848
return 5.25;
4949
}
5050
/** Clicks registered within this amount of time are registered as double clicks */
51-
static get DOUBLE_CLICK_MILLIS () {
51+
static get DOUBLE_CLICK_MILLIS() {
5252
return 250;
5353
}
5454
/**
@@ -59,7 +59,7 @@ class ReshapeTool extends paper.Tool {
5959
* @param {!function} onUpdateImage A callback to call when the image visibly changes
6060
* @param {!function} switchToTextTool A callback to call to switch to the text tool
6161
*/
62-
constructor (setHoveredItem, clearHoveredItem, setSelectedItems, clearSelectedItems, onUpdateImage,
62+
constructor(setHoveredItem, clearHoveredItem, setSelectedItems, clearSelectedItems, onUpdateImage,
6363
switchToTextTool) {
6464
super();
6565
this.setHoveredItem = setHoveredItem;
@@ -97,7 +97,7 @@ class ReshapeTool extends paper.Tool {
9797
* to be grabbable. (Segments are the little circles)
9898
* @return {object} See paper.Item.hitTest for definition of options
9999
*/
100-
getSelectedSegmentHitOptions () {
100+
getSelectedSegmentHitOptions() {
101101
const hitOptions = {
102102
segments: true,
103103
tolerance: ReshapeTool.TOLERANCE / paper.view.zoom,
@@ -116,7 +116,7 @@ class ReshapeTool extends paper.Tool {
116116
* legitimate hits on other things (like if the handle is over part of the fill). (Handles are the diamonds)
117117
* @return {object} See paper.Item.hitTest for definition of options
118118
*/
119-
getHandleHitOptions () {
119+
getHandleHitOptions() {
120120
const hitOptions = {
121121
handles: true,
122122
tolerance: ReshapeTool.TOLERANCE / paper.view.zoom,
@@ -137,7 +137,7 @@ class ReshapeTool extends paper.Tool {
137137
* unselected things and fills.
138138
* @return {object} See paper.Item.hitTest for definition of options
139139
*/
140-
getSelectedStrokeHitOptions () {
140+
getSelectedStrokeHitOptions() {
141141
const hitOptions = {
142142
segments: false,
143143
stroke: false,
@@ -161,7 +161,7 @@ class ReshapeTool extends paper.Tool {
161161
* selected.
162162
* @return {object} See paper.Item.hitTest for definition of options
163163
*/
164-
getUnselectedAndFillHitOptions () {
164+
getUnselectedAndFillHitOptions() {
165165
const hitOptions = {
166166
fill: true,
167167
stroke: true,
@@ -181,15 +181,15 @@ class ReshapeTool extends paper.Tool {
181181
* @param {paper.Item} prevHoveredItemId ID of the highlight item that indicates the mouse is
182182
* over a given item currently
183183
*/
184-
setPrevHoveredItemId (prevHoveredItemId) {
184+
setPrevHoveredItemId(prevHoveredItemId) {
185185
this.prevHoveredItemId = prevHoveredItemId;
186186
}
187187
/**
188188
* Given the point at which the mouse is, return the prioritized hit result, or null if nothing was hit.
189189
* @param {paper.Point} point Point to hit test on canvas
190190
* @return {?paper.HitResult} hitResult
191191
*/
192-
getHitResult (point) {
192+
getHitResult(point) {
193193
// Prefer hits on segments to other types of hits, since segments always overlap curves.
194194
let hitResults =
195195
paper.project.hitTestAll(point, this.getSelectedSegmentHitOptions());
@@ -215,7 +215,7 @@ class ReshapeTool extends paper.Tool {
215215
}
216216
return hitResult;
217217
}
218-
handleMouseDown (event) {
218+
handleMouseDown(event) {
219219
if (event.event.button > 0) return; // only first mouse button
220220
this.active = true;
221221
this.clearHoveredItem();
@@ -248,9 +248,9 @@ class ReshapeTool extends paper.Tool {
248248
// If item is not yet selected, don't behave differently depending on if they clicked a segment
249249
// (since those were invisible), just select the whole thing as if they clicked the fill.
250250
if (!hitResult.item.selected ||
251-
hitResult.type === 'fill' ||
252-
hitResult.type === 'stroke' ||
253-
(hitResult.type !== 'segment' && doubleClicked)) {
251+
hitResult.type === 'fill' ||
252+
hitResult.type === 'stroke' ||
253+
(hitResult.type !== 'segment' && doubleClicked)) {
254254
this.mode = ReshapeModes.FILL;
255255
this._modeMap[this.mode].onMouseDown(hitProperties);
256256
} else if (hitResult.type === 'segment') {
@@ -273,7 +273,7 @@ class ReshapeTool extends paper.Tool {
273273
this._modeMap[this.mode].onMouseDown(hitProperties);
274274
}
275275
}
276-
handleMouseMove (event) {
276+
handleMouseMove(event) {
277277
const hitResult = this.getHitResult(event.point);
278278
let hoveredItem;
279279

@@ -289,17 +289,17 @@ class ReshapeTool extends paper.Tool {
289289
}
290290

291291
if ((!hoveredItem && this.prevHoveredItemId) || // There is no longer a hovered item
292-
(hoveredItem && !this.prevHoveredItemId) || // There is now a hovered item
293-
(hoveredItem && this.prevHoveredItemId &&
294-
hoveredItem.id !== this.prevHoveredItemId)) { // hovered item changed
292+
(hoveredItem && !this.prevHoveredItemId) || // There is now a hovered item
293+
(hoveredItem && this.prevHoveredItemId &&
294+
hoveredItem.id !== this.prevHoveredItemId)) { // hovered item changed
295295
this.setHoveredItem(hoveredItem ? hoveredItem.id : null);
296296
}
297297
}
298-
handleMouseDrag (event) {
298+
handleMouseDrag(event) {
299299
if (event.event.button > 0 || !this.active) return; // only first mouse button
300300
this._modeMap[this.mode].onMouseDrag(event);
301301
}
302-
handleMouseUp (event) {
302+
handleMouseUp(event) {
303303
if (event.event.button > 0 || !this.active) return; // only first mouse button
304304
if (this.mode === ReshapeModes.SELECTION_BOX) {
305305
this._modeMap[this.mode].onMouseUpVector(event);
@@ -309,7 +309,7 @@ class ReshapeTool extends paper.Tool {
309309
this.mode = ReshapeModes.SELECTION_BOX;
310310
this.active = false;
311311
}
312-
handleKeyDown (event) {
312+
handleKeyDown(event) {
313313
if (event.event.target instanceof HTMLInputElement || event.event.target instanceof HTMLTextAreaElement) {
314314
// Ignore nudge if a text input field is focused
315315
return;
@@ -329,15 +329,19 @@ class ReshapeTool extends paper.Tool {
329329
} else if (event.key === 'right') {
330330
translation = new paper.Point(nudgeAmount, 0);
331331
} else if (event.key == 'i' || event.key == 'o') {
332-
332+
333333
const segments = getSelectedSegments();
334334
for (const seg of segments) {
335335
let parent = seg.path;
336336
let p = seg.point;
337+
let o = parent.getOffsetOf(p);
338+
let o1 = o + 0.01;
339+
let o2 = o + (parent.length - 0.01);
340+
let n = (parent.getNormalAt(o1 % parent.length).add(parent.getNormalAt(o2 % parent.length))).divide(2);
337341
if (event.key == 'o') {
338-
seg.point = p.add(parent.getNormalAt(parent.getOffsetOf(p)));
342+
seg.point = p.add(n);
339343
} else {
340-
seg.point = p.subtract(parent.getNormalAt(parent.getOffsetOf(p)));
344+
seg.point = p.subtract(n);
341345
}
342346
}
343347
}
@@ -356,15 +360,15 @@ class ReshapeTool extends paper.Tool {
356360
}
357361
}
358362
}
359-
handleKeyUp (event) {
363+
handleKeyUp(event) {
360364
const selected = getSelectedLeafItems();
361365
if (selected.length === 0) return;
362366

363367
if (event.key === 'up' || event.key === 'down' || event.key === 'left' || event.key === 'right') {
364368
this.onUpdateImage();
365369
}
366370
}
367-
deactivateTool () {
371+
deactivateTool() {
368372
paper.settings.handleSize = 0;
369373
this.clearHoveredItem();
370374
this.setHoveredItem = null;

src/helper/tools/triangle-tool.js

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,26 @@ const sideCount = {
1010
value: 3
1111
};
1212

13+
const pointCount = {
14+
value: 1
15+
};
16+
1317
/**
1418
* Tool for drawing triangles.
1519
*/
1620
class TriangleTool extends paper.Tool {
17-
static set sideCount (value) {
21+
static set sideCount(value) {
1822
sideCount.value = value;
1923
}
20-
static get sideCount () {
24+
static get sideCount() {
2125
return sideCount.value;
2226
}
27+
static set pointCount(value) {
28+
pointCount.value = value;
29+
}
30+
static get pointCount() {
31+
return pointCount.value;
32+
}
2333

2434
static get TOLERANCE() {
2535
return 2;
@@ -123,6 +133,41 @@ class TriangleTool extends paper.Tool {
123133
this.tri.position = event.downPoint.add(dimensions.multiply(0.5));
124134
}
125135

136+
let seg = this.tri.segments;
137+
let newSeg = [[]];
138+
139+
let j = 0;
140+
let oj = 0;
141+
let wasOj = true;
142+
143+
let l = seg.length;
144+
145+
// this is the worst code ever
146+
for (let i = 0; i < l; i++) {
147+
newSeg[newSeg.length - 1].push(seg[j]);
148+
j += TriangleTool.pointCount;
149+
j = j % (seg.length);
150+
if (j == oj && !wasOj) {
151+
j = oj + 1;
152+
oj++;
153+
wasOj = true;
154+
newSeg.push([]);
155+
}
156+
wasOj = false;
157+
}
158+
159+
this.tri.remove();
160+
161+
this.tri = new paper.Path();
162+
163+
for (let s of newSeg) {
164+
let t2 = new paper.Path({ segments: s, closed: true });
165+
let otri = this.tri;
166+
this.tri = otri.unite(t2);
167+
t2.remove();
168+
otri.remove();
169+
}
170+
126171
styleShape(this.tri, this.colorState);
127172
}
128173
handleMouseUp(event) {

src/playground/index.ejs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,5 @@
66
<title><%= htmlWebpackPlugin.options.title %></title>
77
</head>
88
<body>
9-
<script src="/playground/playground.js"></script>
109
</body>
1110
</html>

src/reducers/triangle-mode.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import log from '../log/log';
22
import TriangleTool from '../helper/tools/triangle-tool';
33

44
const CHANGE_TRIANGLE_SIDE_COUNT = 'scratch-paint/triangle-mode/CHANGE_TRIANGLE_SIDE_COUNT';
5-
const initialState = { trianglePolyCount: 3 };
5+
const CHANGE_TRIANGLE_POINT_COUNT = 'scratch-paint/triangle-mode/CHANGE_TRIANGLE_POINT_COUNT';
6+
const initialState = { trianglePolyCount: 3, trianglePointCount: 1 };
67

78
const reducer = function (state, action) {
89
if (typeof state === 'undefined') state = initialState;
@@ -12,9 +13,18 @@ const reducer = function (state, action) {
1213
log.warn(`Invalid side count: ${action.trianglePolyCount}`);
1314
return state;
1415
}
15-
const value = Math.max(3, action.trianglePolyCount);
16+
const value = Math.floor(Math.max(3, action.trianglePolyCount));
1617
TriangleTool.sideCount = value;
17-
return { trianglePolyCount: value };
18+
return { trianglePolyCount: value, trianglePointCount: state.trianglePointCount };
19+
20+
case CHANGE_TRIANGLE_POINT_COUNT:
21+
if (isNaN(action.trianglePointCount)) {
22+
log.warn(`Invalid side count: ${action.trianglePointCount}`);
23+
return state;
24+
}
25+
const value2 = Math.floor(Math.max(1, action.trianglePointCount));
26+
TriangleTool.pointCount = value2;
27+
return { trianglePointCount: value2, trianglePolyCount: state.trianglePolyCount };
1828
default:
1929
return state;
2030
}
@@ -28,7 +38,15 @@ const changeTrianglePolyCount = function (trianglePolyCount) {
2838
};
2939
};
3040

41+
const changeTrianglePointCount = function (trianglePointCount) {
42+
return {
43+
type: CHANGE_TRIANGLE_POINT_COUNT,
44+
trianglePointCount: trianglePointCount
45+
};
46+
};
47+
3148
export {
3249
reducer as default,
33-
changeTrianglePolyCount
50+
changeTrianglePolyCount,
51+
changeTrianglePointCount
3452
};

0 commit comments

Comments
 (0)