Skip to content

Commit f475331

Browse files
committed
fix inset/outset for weird normals
1 parent c084d52 commit f475331

File tree

1 file changed

+35
-31
lines changed

1 file changed

+35
-31
lines changed

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;

0 commit comments

Comments
 (0)