diff options
author | bobzel <zzzman@gmail.com> | 2023-05-02 12:37:04 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2023-05-02 12:37:04 -0400 |
commit | 2660a8b454ec86250fc7679df95f76441fb84aad (patch) | |
tree | db29cfee6d827b103aeea175fe9bc65a6dd95cd0 | |
parent | 653ce7a44190d2c3de5dd499ac09986a40b3abd3 (diff) |
fixed ink erasing when stroke intersects at endpoint. attempted performance improvement as well. bug fix for selecting strokes that are not active.
-rw-r--r-- | src/client/views/GestureOverlay.tsx | 12 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 22 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 4 |
3 files changed, 29 insertions, 9 deletions
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 13faae783..b04769c1e 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -658,9 +658,9 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> { } possibilities.push(...wR?.alternates?.map((a: any) => a.recognizedString)); } - const r = Math.max(this.svgBounds.right, ...this._strokes.map(s => this.getBounds(s).right)); - const l = Math.min(this.svgBounds.left, ...this._strokes.map(s => this.getBounds(s).left)); - const t = Math.min(this.svgBounds.top, ...this._strokes.map(s => this.getBounds(s).top)); + const r = Math.max(this.svgBounds.right, ...this._strokes.map(s => GestureOverlay.getBounds(s).right)); + const l = Math.min(this.svgBounds.left, ...this._strokes.map(s => GestureOverlay.getBounds(s).left)); + const t = Math.min(this.svgBounds.top, ...this._strokes.map(s => GestureOverlay.getBounds(s).top)); // if we receive any word results from cognitive services, display them runInAction(() => { @@ -891,7 +891,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> { detail: { points, gesture, - bounds: this.getBounds(points), + bounds: GestureOverlay.getBounds(points), text, }, }) @@ -899,7 +899,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> { ); }; - getBounds = (stroke: InkData, pad?: boolean) => { + public static getBounds = (stroke: InkData, pad?: boolean) => { const padding = pad ? [-20000, 20000] : []; const xs = [...padding, ...stroke.map(p => p.X)]; const ys = [...padding, ...stroke.map(p => p.Y)]; @@ -911,7 +911,7 @@ export class GestureOverlay extends Touchable<GestureOverlayProps> { }; @computed get svgBounds() { - return this.getBounds(this._points); + return GestureOverlay.getBounds(this._points); } @computed get elements() { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index bab42e560..9cc732008 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -821,6 +821,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection this._lastY = e.clientY; }; + _eraserLock = 0; /** * 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, @@ -830,6 +831,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection @action onEraserMove = (e: PointerEvent, down: number[], delta: number[]) => { const currPoint = { X: e.clientX, Y: e.clientY }; + 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. 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); @@ -837,12 +839,15 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection SetActiveInkColor(StrCast(intersect.inkView.rootDoc.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) { + this._eraserLock++; this.segmentInkStroke(intersect.inkView, intersect.t).forEach(segment => - GestureOverlay.Instance.dispatchGesture( + this.forceStrokeGesture( + e, GestureUtils.Gestures.Stroke, 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[]) ) ); + setTimeout(() => this._eraserLock--); } // Lower ink opacity to give the user a visual indicator of deletion. intersect.inkView.layoutDoc.opacity = 0.5; @@ -851,6 +856,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection }); return false; }; + forceStrokeGesture = (e: PointerEvent, gesture: GestureUtils.Gestures, points: InkData, text?: any) => { + this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, GestureOverlay.getBounds(points), text)); + }; @action onPointerMove = (e: PointerEvent): boolean => { @@ -929,7 +937,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection const docCurveTVal = t + Math.floor(i / 4); if (excludeT < startSegmentT || excludeT > docCurveTVal) { const localStartTVal = startSegmentT - Math.floor(i / 4); - segment.push(inkSegment.split(localStartTVal < 0 ? 0 : localStartTVal, t)); + t !== (localStartTVal < 0 ? 0 : localStartTVal) && segment.push(inkSegment.split(localStartTVal < 0 ? 0 : localStartTVal, t)); segment.length && segments.push(segment); } // start a new segment from the intersection t value @@ -979,11 +987,21 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection if (ink?.Document === otherInk.props.Document && neighboringSegment) continue; const otherCurve = new Bezier(otherCtrlPts.slice(j, j + 4).map(p => ({ x: p.X, y: p.Y }))); + const c0 = otherCurve.get(0); + const c1 = otherCurve.get(1); + const apt = curve.project(c0); + const bpt = curve.project(c1); + if (apt.d !== undefined && apt.d < 1 && apt.t !== undefined && !tVals.includes(apt.t)) { + tVals.push(apt.t); + } this.bintersects(curve, otherCurve).forEach((val: string | number, i: number) => { // Converting the Bezier.js Split type to a t-value number. const t = +val.toString().split('/')[0]; if (i % 2 === 0 && !tVals.includes(t)) tVals.push(t); // bcz: Hack! don't know why but intersection points are doubled from bezier.js (but not identical). }); + if (bpt.d !== undefined && bpt.d < 1 && bpt.t !== undefined && !tVals.includes(bpt.t)) { + tVals.push(bpt.t); + } } }); return tVals; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 4876ef300..3bdd2bf6e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -47,6 +47,7 @@ import { LinkAnchorBox } from './LinkAnchorBox'; import { PresEffect, PresEffectDirection } from './trails'; import { PinProps, PresBox } from './trails/PresBox'; import React = require('react'); +import { InkingStroke } from '../InkingStroke'; const { Howl } = require('howler'); interface Window { @@ -869,11 +870,12 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps contentPointerEvents = () => (!this.disableClickScriptFunc && this.onClickHandler ? 'none' : this.pointerEvents); @computed get contents() { TraceMobx(); + const isInk = StrCast(this.layoutDoc.layout).includes(InkingStroke.name); return ( <div className="documentView-contentsView" style={{ - pointerEvents: (this.pointerEvents === 'visiblePainted' ? 'none' : this.pointerEvents) ?? 'all', + pointerEvents: (isInk ? 'none' : this.pointerEvents) ?? 'all', height: this.headerMargin ? `calc(100% - ${this.headerMargin}px)` : undefined, }}> {!this._retryThumb || !this.thumbShown() ? null : ( |