From 33761fc2227458acf36a5cc4b1f08eaae6e58695 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Tue, 11 Jun 2024 11:15:25 -0400 Subject: some changes --- .../collectionFreeForm/CollectionFreeFormView.tsx | 170 +++++++++++++-------- 1 file changed, 103 insertions(+), 67 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d22b3569e..e66dbd796 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -144,7 +144,10 @@ export class CollectionFreeFormView extends CollectionSubView { + erase = (e: PointerEvent, delta: number[]) => { const currPoint = { X: e.clientX, Y: e.clientY }; this._eraserPts.push([currPoint.X, currPoint.Y]); this._eraserPts = this._eraserPts.slice(Math.max(0, this._eraserPts.length - 5)); - // if (this._eraserLock) return false; // leaving this commented out in case the idea is revisited in the future - this.getEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint).forEach(intersect => { - if (!this._deleteList.includes(intersect.inkView)) { - this._deleteList.push(intersect.inkView); - 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 (Doc.ActiveTool !== InkTool.StrokeEraser) { - // this._eraserLock++; - const 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 - const newStrokes = segments?.map(segment => { - const points = segment.reduce((data, curve) => [...data, ...curve.points.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]); - const bounds = InkField.getBounds(points); - const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); - const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; - return Docs.Create.InkDocument( - points, - { title: 'stroke', + if (Doc.ActiveTool === InkTool.RadiusEraser) { + const strokeMap: Map = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); + + strokeMap.forEach((intersects, stroke) => { + if (!this._deleteList.includes(stroke)) { + this._deleteList.push(stroke); + SetActiveInkWidth(StrCast(stroke.Document.stroke_width?.toString()) || '1'); + SetActiveInkColor(StrCast(stroke.Document.color?.toString()) || 'black'); + const segments = this.radiusErase(stroke, intersects.sort()); + segments?.forEach(segment => + this.forceStrokeGesture( + e, + Gestures.Stroke, + segment.reduce((data, curve) => [...data, ...curve.points.map(p => stroke.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]) + ) + ); + } + stroke.layoutDoc.opacity = 0; + stroke.layoutDoc.dontIntersect = true; + }); + } else { + this.getEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint).forEach(intersect => { + if (!this._deleteList.includes(intersect.inkView)) { + this._deleteList.push(intersect.inkView); + 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 (Doc.ActiveTool !== InkTool.StrokeEraser) { + // this._eraserLock++; + const 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 + const newStrokes = segments?.map(segment => { + const points = segment.reduce((data, curve) => [...data, ...curve.points.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]); + const bounds = InkField.getBounds(points); + const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); + const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; + return Docs.Create.InkDocument( + points, + { title: 'stroke', x: B.x - inkWidth / 2, y: B.y - inkWidth / 2, _width: B.width + inkWidth, _height: B.height + inkWidth, stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore - inkWidth - ); - }); - newStrokes && this.addDocument?.(newStrokes); - // setTimeout(() => this._eraserLock--); + inkWidth + ); + }); + newStrokes && this.addDocument?.(newStrokes); + // setTimeout(() => this._eraserLock--); + } + // Lower ink opacity to give the user a visual indicator of deletion. + intersect.inkView.layoutDoc.opacity = 0; + intersect.inkView.layoutDoc.dontIntersect = true; } - // Lower ink opacity to give the user a visual indicator of deletion. - intersect.inkView.layoutDoc.opacity = 0; - intersect.inkView.layoutDoc.dontIntersect = true; - } - }); + }); + } + return false; + }; + + /** + * Erases strokes by intersecting them with an invisible "eraser stroke". + * By default this iterates through all intersected ink strokes, determines their segmentation, draws back the non-intersected segments, + * and deletes the original stroke. + */ + @action + onEraserMove = (e: PointerEvent, down: number[], delta: number[]) => { + this.erase(e, delta); + // if (this._eraserLock) return false; // leaving this commented out in case the idea is revisited in the future + return false; + }; + + @action + onEraserClick = (e: PointerEvent, doubleTap?: boolean) => { + this.erase(e, [0, 0]); return false; }; @@ -720,7 +753,7 @@ export class CollectionFreeFormView extends CollectionSubView { - SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY); - if (SmartDrawHandler.Instance.strokes.length > 0) { - const strokeList: InkData[] = SmartDrawHandler.Instance.strokes; - strokeList.forEach(coords => { - // const stroke = new InkField(coords); - // const points = coords.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.X, Y: p.Y }) ?? { X: 0, Y: 0 }), [] as PointData[]); - const bounds = InkField.getBounds(coords); - const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); - const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; - const inkDoc = Docs.Create.InkDocument( - coords, - { title: 'stroke', + SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY, this.createInkStroke); + }; + + @action + createInkStroke = (strokeList: InkData[]) => { + strokeList.forEach(coords => { + // const stroke = new InkField(coords); + // const points = coords.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.X, Y: p.Y }) ?? { X: 0, Y: 0 }), [] as PointData[]); + const bounds = InkField.getBounds(coords); + const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); + const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; + const inkDoc = Docs.Create.InkDocument( + coords, + { title: 'stroke', x: B.x - inkWidth / 2, y: B.y - inkWidth / 2, _width: B.width + inkWidth, _height: B.height + inkWidth, stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore - inkWidth - ); - this.addDocument(inkDoc); - }); - } + inkWidth + ); + this.addDocument(inkDoc); + }); }; @action @@ -1849,8 +1883,10 @@ export class CollectionFreeFormView extends CollectionSubView { - this._eraserX = e.clientX; - this._eraserY = e.clientY; + const locPt = this.ScreenToLocalBoxXf().transformPoint(e.clientX, e.clientY); + this._eraserX = locPt[0]; + this._eraserY = locPt[1]; + // Doc.ActiveTool === InkTool.RadiusEraser ? this._childPointerEvents = 'none' : this._childPointerEvents = 'all' // super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); }; @@ -2161,8 +2197,8 @@ export class CollectionFreeFormView extends CollectionSubView