From f8053c9d1f7d849cc0c3e8c0b8bf4a466ffd85b9 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Tue, 14 May 2024 13:01:51 -0400 Subject: some bug fixes --- .../collectionFreeForm/CollectionFreeFormView.tsx | 152 ++++++++++++++------- 1 file changed, 102 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 622189b80..14d20eb4a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -95,8 +95,6 @@ export class CollectionFreeFormView extends CollectionSubView(); @observable _brushedView: { width: number; height: number; panX: number; panY: number } | undefined = undefined; // highlighted region of freeform canvas used by presentations to indicate a region @observable GroupChildDrag: boolean = false; // child document view being dragged. needed to update drop areas of groups when a group item is dragged. + @observable _eraserX: number = 0; + @observable _eraserY: number = 0; + @observable _showEraserCircle: boolean = false; // to determine whether the radius eraser should show @computed get contentViews() { const viewsMask = this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z && ele.inkMask !== -1 && ele.inkMask !== undefined).map(ele => ele.ele); @@ -747,7 +749,7 @@ export class CollectionFreeFormView extends CollectionSubView { if (!this._deleteList.includes(intersect.inkView)) { this._deleteList.push(intersect.inkView); @@ -755,7 +757,7 @@ export class CollectionFreeFormView extends CollectionSubView { 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[]); @@ -784,23 +786,34 @@ export class CollectionFreeFormView extends CollectionSubView { - // this._eraserX = e.clientX; - // this._eraserY = e.clientY; + // const currZoom = this.zoomScaling(); + // console.log("curr zoom", currZoom); + // console.log("prev zoom", this.prevZoom); 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; // bcz: should be fixed by putting it on a queue to be processed after the last eraser movement is processed. - const strokeMap: Map = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); + const intersections: any[] = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); + // if (intersections[0].size > 0 && currZoom === this.prevZoom) { + const strokeMap: Map = intersections[0]; + const eraserStroke = intersections[1]; + 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'); - this._eraserLock++; - // create a new curve by appending all curves of the current segment together in order to render a single new stroke. - const segments = this.radiusErase(stroke, intersects.sort()); + const segments = this.radiusErase(stroke, intersects.sort(), eraserStroke); segments?.forEach(segment => this.forceStrokeGesture( e, @@ -808,12 +821,16 @@ export class CollectionFreeFormView extends CollectionSubView [...data, ...curve.points.map(p => stroke.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]) ) ); - setTimeout(() => this._eraserLock--); } - // Lower ink opacity to give the user a visual indicator of deletion. stroke.layoutDoc.opacity = 0; stroke.layoutDoc.dontIntersect = true; }); + // } else if (intersections[0].length > 0) { + // this.prevZoom = currZoom; + // console.log("skipping occurred"); + // } else if (this.prevZoom = currZoom) { + // this.prevZoom = currZoom; + // } return false; }; @@ -834,8 +851,16 @@ export class CollectionFreeFormView extends CollectionSubView { - const radius = ActiveEraserWidth() + 3; // add 3 to avoid eraser being too thin + /** + * Creates the eraser outline for a radius eraser. The outline be + * @param startInkCoordsIn + * @param endInkCoordsIn + * @param inkStrokeWidth + * @returns + */ + createEraserOutline = (startInkCoordsIn: { X: number; Y: number }, endInkCoordsIn: { X: number; Y: number }, inkStrokeWidth: number) => { + // increase radius slightly based on the erased stroke's width, added to make eraser look more realistic + var radius = ActiveEraserWidth() + inkStrokeWidth * 0.2; const c = 0.551915024494; // circle tangent length to side ratio const movement = { x: endInkCoordsIn.X - startInkCoordsIn.X, y: endInkCoordsIn.Y - startInkCoordsIn.Y }; const moveLen = Math.sqrt(movement.x ** 2 + movement.y ** 2); @@ -959,8 +984,13 @@ export class CollectionFreeFormView extends CollectionSubView { - const eraserRadius = ActiveEraserWidth() + 3; + const eraserRadius = ActiveEraserWidth() / this.zoomScaling(); const eraserMin = { X: Math.min(lastPoint.X, currPoint.X) - eraserRadius, Y: Math.min(lastPoint.Y, currPoint.Y) - eraserRadius }; const eraserMax = { X: Math.max(lastPoint.X, currPoint.X) + eraserRadius, Y: Math.max(lastPoint.Y, currPoint.Y) + eraserRadius }; const strokeToTVals = new Map(); @@ -976,12 +1006,14 @@ export class CollectionFreeFormView extends CollectionSubView= inkViewBounds.left && eraserMax.Y >= inkViewBounds.top ); - + const erasers: InkData[] = []; intersectingStrokes.forEach(({ inkStroke, inkView }) => { - const { inkData } = inkStroke.inkScaledData(); + const { inkData, inkStrokeWidth } = inkStroke.inkScaledData(); const prevPointInkSpace = inkStroke.ptFromScreen(lastPoint); const currPointInkSpace = inkStroke.ptFromScreen(currPoint); - const eraserInkData = this.createEraserOutline(prevPointInkSpace, currPointInkSpace).inkData; + const eraserInkData = this.createEraserOutline(prevPointInkSpace, currPointInkSpace, inkStrokeWidth).inkData; + // erasers.push(eraserInkData); + // add the ends of the stroke in as "intersections" if (this.insideEraserOutline(eraserInkData, inkData[0])) { strokeToTVals.set(inkView, [0]); @@ -994,6 +1026,7 @@ export class CollectionFreeFormView extends CollectionSubView Math.abs(val - (t + Math.floor(i / 4))) <= tValOffset); if (!inList) { inkList.push(t + Math.floor(i / 4)); @@ -1019,33 +1052,43 @@ export class CollectionFreeFormView extends CollectionSubView { + radiusErase = (ink: DocumentView, tVals: number[], erasers: InkData[]): Segment[] => { const segments: Segment[] = []; + var eraser: Segment = []; + // for (var i = 0; i < erasers.length; i ++) { + // for (var j = 0; j < erasers[i].length - 3; j +=4) { + // eraser.push(InkField.Segment(erasers[i], j)); + // } + // segments.push(eraser); + // eraser = []; + // } + const inkStroke = ink?.ComponentView as InkingStroke; const { inkData } = inkStroke.inkScaledData(); var currSegment: Segment = []; if (tVals.length % 2 !== 0) { - // should always have even tVals + // any radius erase stroke will always result in even tVals, since the ends are included for (var i = 0; i < inkData.length - 3; i += 4) { currSegment.push(InkField.Segment(inkData, i)); } segments.push(currSegment); - return segments; + return segments; // want to return the full original stroke } - var continueErasing = false; - var firstSegment: Segment = []; + var continueErasing = false; // used to erase segments if they are completely enclosed in the eraser + var firstSegment: Segment = []; // used to keep track of the first segment for closed curves + // early return if nothing to split on if (tVals.length === 0 || (tVals.length === 1 && tVals[0] === 0)) { for (var i = 0; i < inkData.length - 3; i += 4) { @@ -1055,26 +1098,28 @@ export class CollectionFreeFormView extends CollectionSubView t >= currCurveT && t < currCurveT + 1); if (segmentTs.length > 0) { for (var j = 0; j < segmentTs.length; j++) { - // if the first end of the segment is within the eraser - if (segmentTs[j] === 0) { + if (segmentTs[j] === 0) { // if the first end of the segment is within the eraser continueErasing = true; - } else if (segmentTs[j] === Math.floor(inkData.length / 4) + 1) { + } else if (segmentTs[j] === Math.floor(inkData.length / 4) + 1) { // the last end break; } else { if (!continueErasing) { currSegment.push(inkBezier.split(0, segmentTs[j] - currCurveT)); continueErasing = true; - } else { + } else { // we've reached the end of the part to take out... continueErasing = false; if (currSegment.length > 0) { - segments.push(currSegment); + segments.push(currSegment); // ...so we add it to the list and reset currSegment if (firstSegment.length === 0) { firstSegment = currSegment; } @@ -1091,15 +1136,14 @@ export class CollectionFreeFormView extends CollectionSubView 0) { + // add the first segment onto the last to avoid fragmentation for closed curves if (InkingStroke.IsClosed(inkData)) { currSegment = currSegment.concat(firstSegment); } segments.push(currSegment); } - if (segments.length === 0) { - console.log("segments is 0"); - } return segments; }; @@ -1219,6 +1263,7 @@ export class CollectionFreeFormView extends CollectionSubView 0 && segment2.length > 0) { segment2 = segment2.concat(segment1); segment1 = []; @@ -1439,7 +1484,7 @@ export class CollectionFreeFormView extends CollectionSubView { this._eraserX = e.clientX; this._eraserY = e.clientY; + if (this._eraserX < 0 || this._eraserY < 0) { + this._showEraserCircle = false; + } else { + this._showEraserCircle = true; + } // super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); }; @@ -2286,19 +2336,21 @@ export class CollectionFreeFormView extends CollectionSubView - {/*
*/} + {Doc.ActiveTool === InkTool.RadiusEraser && ( +
+ )} {this.paintFunc ? ( // need this so that any live dashfieldviews will update the underlying text that the code eval reads ) : this._lightboxDoc ? ( -- cgit v1.2.3-70-g09d2