diff options
Diffstat (limited to 'src/client/views')
| -rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 165 |
1 files changed, 82 insertions, 83 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 18b75d8ff..da4c53d66 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -610,10 +610,21 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection // group freeforms don't pan when dragged -- instead let the event go through to allow the group itself to drag // prettier-ignore switch (Doc.ActiveTool) { - case InkTool.Highlighter: break; - case InkTool.Write: break; - case InkTool.Pen: break; // the GestureOverlay handles ink stroke input -- either as gestures, or drying as ink strokes that are added to document views - case InkTool.Eraser: + case InkTool.Highlighter: + break; + case InkTool.Write: + break; + case InkTool.Pen: + break; // the GestureOverlay handles ink stroke input -- either as gestures, or drying as ink strokes that are added to document views + case InkTool.StrokeEraser: + this._batch = UndoManager.StartBatch('collectionErase'); + setupMoveUpEvents(this, e, this.onEraserMove, this.onEraserUp, emptyFunction); + break; + case InkTool.SegmentEraser: + this._batch = UndoManager.StartBatch('collectionErase'); + setupMoveUpEvents(this, e, this.onEraserMove, this.onEraserUp, emptyFunction); + break; + case InkTool.RadiusEraser: this._batch = UndoManager.StartBatch('collectionErase'); setupMoveUpEvents(this, e, this.onEraserMove, this.onEraserUp, emptyFunction); break; @@ -738,28 +749,19 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection SetActiveInkWidth(StrCast(intersect.inkView.Document.stroke_width?.toString()) || '1'); SetActiveInkColor(StrCast(intersect.inkView.Document.color?.toString()) || 'black'); // create a new curve by appending all curves of the current segment together in order to render a single new stroke. - if (!e.shiftKey) { + if (Doc.ActiveTool !== InkTool.StrokeEraser) { this._eraserLock++; - const segments = this.segmentInkStroke(intersect.inkView, intersect.t); // intersect.t is where the eraser intersected the ink stroke - want to remove the segment that starts at the intersection just before this t value and goes to the one just after it - // we delete the original ink stroke, then create new strokes for each of the remaining segments - // we do this through the hack of calling the stroke Gesture code as if the strokes had just be drawn by hand - // [[(0,0), (3,7), (9,4), (4,5)],[(4,5), (13,17), (19,14), (14,15)], [(23,19),(...}]] - // [[(0,0), (3,7), (9,4), (4,5), (13,17), (19,14), (14,15)], [(23,19),(...}]] - // segments.map(segment => segment.map(pt => pt)) - // segments[0][3].x === segments[1][0].x - - // 3 == "3" true - // 3 === "3" falsen !== - - // for (var i = 0; i < segments.length; i ++) { - // if (segments[i][0].points.lastElement().x === segments[i+1][0].points.lastElement().x && segments[i][0].points.lastElement().y === segments[i+1][0].points.lastElement().y) { - // segments[i][0].points.pop(); - // segments[i][0].points = segments[i][0].points.concat(segments[i+1][0].points); - // segments.splice(i+1, 1); - // } - // i++; + var segments; + if (Doc.ActiveTool === InkTool.SegmentEraser) { + segments = this.segmentErase(intersect.inkView, intersect.t); // intersect.t is where the eraser intersected the ink stroke - want to remove the segment that starts at the intersection just before this t value and goes to the one just after it + } else if (Doc.ActiveTool === InkTool.RadiusEraser) { + console.log("RADIUS"); + segments = this.radiusErase(intersect.inkView, intersect.t); + } + // } else if (Doc.ActiveTool === InkTool.RadiusEraser) { + // segments = undefined; // } - segments.forEach(segment => + segments?.forEach(segment => this.forceStrokeGesture( e, GestureUtils.Gestures.Stroke, @@ -837,6 +839,42 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection ); }; + @action + radiusErase = (ink: DocumentView, eraseT: number): Segment[] => { + const segments: Segment[] = []; + var segment1: Segment = []; + var segment2: Segment = []; + const eraseWidth = ActiveInkWidth() / 100; + const { inkData } = (ink?.ComponentView as InkingStroke).inkScaledData(); + for (var i = 0; i < inkData.length - 3; i += 4) { + const currCurveT = Math.floor(i/4); + const inkSegment: Bezier = InkField.Segment(inkData, i); + if (eraseT >= currCurveT && eraseT < currCurveT+1) { + if (eraseT - eraseWidth > currCurveT && eraseT + eraseWidth < currCurveT + 1) { + segment1.push(inkSegment.split(0, eraseT - currCurveT - eraseWidth)); + segment2.push(inkSegment.split(eraseT - currCurveT + eraseWidth, 1)); + } else if (eraseT - eraseWidth < currCurveT) { + segment2.push(inkSegment.split(eraseT - currCurveT + eraseWidth, 1)); + } else if (eraseT + eraseWidth > currCurveT + 1) { + segment1.push(inkSegment.split(0, eraseT - currCurveT - eraseWidth)); + } + } else if (eraseT > currCurveT + 1) { + segment1.push(inkSegment); + } else { + segment2.push(inkSegment); + } + } + + // push 1 or both segments if they are not empty + if (segment1.length && (Math.abs(segment1[0].points[0].x - segment1[0].points.lastElement().x) > 0.5 || Math.abs(segment1[0].points[0].y - segment1[0].points.lastElement().y) > 0.5)) { + segments.push(segment1); + } + if (segment2.length && (Math.abs(segment2[0].points[0].x - segment2[0].points.lastElement().x) > 0.5 || Math.abs(segment2[0].points[0].y - segment2[0].points.lastElement().y) > 0.5)) { + segments.push(segment2); + } + return segments; + } + /** * Erases ink strokes by segments. Locates intersections of the current ink stroke with all other ink strokes (including itself), * then erases the segment that was intersected by the eraser. This is done by creating either 1 or two resulting segments @@ -846,7 +884,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection * @returns The ink stroke represented as a list of segments, excluding the segment in which the eraser intersection occurred. */ @action - segmentInkStroke = (ink: DocumentView, excludeT: number): Segment[] => { + segmentErase = (ink: DocumentView, excludeT: number): Segment[] => { const segments: Segment[] = []; var segment1: Segment = []; @@ -873,8 +911,17 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection var isClosedCurve = false; if (intersections[0] === 0) { isClosedCurve = true; - intersections = intersections.slice(1, intersections.length ); // take the 0 intersection out - segmentIndexes = segmentIndexes.slice(1, segmentIndexes.length); // same for indexes + + // now reduce intersections list to the actual intersections because closed curves have additional ones with itself + const indices = intersections + .map((value, index) => value > 0.0001 && value < Math.floor(inkData.length / 4) ? index : -1) + .filter(index => index !== -1); + + // Filter intersections and segmentIndexes based on validIndices + intersections = indices.map(index => intersections[index]); + segmentIndexes = indices.map(index => segmentIndexes[index]); + // intersections = intersections.slice(1, intersections.length ); // take the 0 intersection out + // segmentIndexes = segmentIndexes.slice(1, segmentIndexes.length); // same for indexes } if (intersections.length) { @@ -938,13 +985,16 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection } } } else { // case where right end is erased - if (currCurveT === splitSegment1) { - segment1.push(inkSegment.split(0, intersections[closestTs[0]] - currCurveT)); - hasSplit = true; - } else if (isClosedCurve && currCurveT === segmentIndexes[1]) { + if (currCurveT === segmentIndexes[0] && isClosedCurve) { segment1.push(inkSegment.split(intersections[0] - currCurveT, 1)); + hasSplit = true; + } else if (currCurveT === splitSegment1) { + segment1.push(inkSegment.split(0, intersections[closestTs[0]] - currCurveT)); + hasSplit = false; // although this is not technically true, we set to false so the segments after don't get added + // } else if (isClosedCurve && currCurveT === segmentIndexes[1]) { + // segment1.push(inkSegment.split(intersections[0] - currCurveT, 1)); } else { - if (!hasSplit && !isClosedCurve) { + if ((isClosedCurve && hasSplit) || (!isClosedCurve && !hasSplit)) { segment1.push(inkSegment); } } @@ -961,57 +1011,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection } return segments; - - - // const segments: Segment[] = []; - // var segment1: Segment = []; - // var segment2: Segment = []; - // var startSegmentT = 0; - // var hasSplit = false; - // const { inkData } = (ink?.ComponentView as InkingStroke).inkScaledData(); - // // This iterates through all segments of the curve and splits them where they intersect another curve. - // // if 'excludeT' is specified, then any segment containing excludeT will be skipped (ie, deleted) - // for (var i = 0; i < inkData.length - 3; i += 4) { - // const inkSegment = InkField.Segment(inkData, i); - // // Getting all t-value intersections of the current curve with all other curves. - // const tVals = this.getInkIntersections(i, ink, inkSegment).sort(); - // if (tVals.length) { - // tVals.forEach((t, index) => { - // const docCurveTVal = t + Math.floor(i / 4); - // if (excludeT < startSegmentT || excludeT > docCurveTVal) { - // const localStartTVal = startSegmentT - Math.floor(i / 4); - // if (!hasSplit) { - // t !== (localStartTVal < 0 ? 0 : localStartTVal) && segment1.push(inkSegment.split(localStartTVal < 0 ? 0 : localStartTVal, t)); - // } else { - // t !== (localStartTVal < 0 ? 0 : localStartTVal) && segment2.push(inkSegment.split(localStartTVal < 0 ? 0 : localStartTVal, t)); - // } - // // if (segment.length && (Math.abs(segment[0].points[0].x - segment[0].points.lastElement().x) > 0.5 || Math.abs(segment[0].points[0].y - segment[0].points.lastElement().y) > 0.5)) segments.push(segment); - // } - // // start a new segment from the intersection t value - // if (tVals.length - 1 === index) { - // const split = inkSegment.split(t).right; - // if (!hasSplit) { - // if (split && (Math.abs(split.points[0].x - split.points.lastElement().x) > 0.5 || Math.abs(split.points[0].y - split.points.lastElement().y) > 0.5)) segment1.push(split); - // } else { - // if (split && (Math.abs(split.points[0].x - split.points.lastElement().x) > 0.5 || Math.abs(split.points[0].y - split.points.lastElement().y) > 0.5)) segment2.push(split); - // } - // } - // startSegmentT = docCurveTVal; - // }); - // } else { - // if (!hasSplit) { - // segment1.push(inkSegment); - // } else { - // segment2.push(inkSegment); - // } - // } - // } - // if (segment1.length && (Math.abs(segment1[0].points[0].x - segment1[0].points.lastElement().x) > 0.5 || Math.abs(segment1[0].points[0].y - segment1[0].points.lastElement().y) > 0.5)) { - // segments.push(segment1); - // } - // if (segment2.length && (Math.abs(segment2[0].points[0].x - segment2[0].points.lastElement().x) > 0.5 || Math.abs(segment2[0].points[0].y - segment2[0].points.lastElement().y) > 0.5)) { - // segments.push(segment2); - // } }; /** |
