From 9787cafc0697b440a6c3a8dfd211e74e7626b39e Mon Sep 17 00:00:00 2001 From: Steve Ruiz Date: Sat, 11 Sep 2021 17:01:59 +0100 Subject: [PATCH] Fix drawing session, avoids expensive iterations if we can --- .../tldraw/src/shape/shapes/arrow/arrow.tsx | 4 +-- .../tldraw/src/shape/shapes/draw/draw.tsx | 21 +++-------- .../src/shape/shapes/ellipse/ellipse.tsx | 6 ++-- .../tldraw/src/shape/shapes/group/group.tsx | 4 +-- .../src/shape/shapes/rectangle/rectangle.tsx | 5 --- .../session/sessions/draw/draw.session.ts | 36 +++++++++++++++---- 6 files changed, 41 insertions(+), 35 deletions(-) diff --git a/packages/tldraw/src/shape/shapes/arrow/arrow.tsx b/packages/tldraw/src/shape/shapes/arrow/arrow.tsx index 6335772d0..cdf4a9c7d 100644 --- a/packages/tldraw/src/shape/shapes/arrow/arrow.tsx +++ b/packages/tldraw/src/shape/shapes/arrow/arrow.tsx @@ -72,7 +72,7 @@ export class Arrow extends TLDrawShapeUtil { } render = React.forwardRef>( - ({ shape, meta, events }) => { + ({ shape, meta, events }, ref) => { const { handles: { start, bend, end }, decorations = {}, @@ -220,7 +220,7 @@ export class Arrow extends TLDrawShapeUtil { const sw = strokeWidth * 1.618 return ( - + {shaftPath} {startArrowHead && ( diff --git a/packages/tldraw/src/shape/shapes/draw/draw.tsx b/packages/tldraw/src/shape/shapes/draw/draw.tsx index abf7f58fe..a0f51185a 100644 --- a/packages/tldraw/src/shape/shapes/draw/draw.tsx +++ b/packages/tldraw/src/shape/shapes/draw/draw.tsx @@ -31,7 +31,7 @@ export class Draw extends TLDrawShapeUtil { } render = React.forwardRef>( - ({ shape, meta, events, isEditing }) => { + ({ shape, meta, events, isEditing }, ref) => { const { points, style } = shape const styles = getShapeStyle(style, meta.isDarkMode) @@ -47,7 +47,7 @@ export class Draw extends TLDrawShapeUtil { const sw = strokeWidth * 0.618 return ( - + { : Utils.getFromCache(this.drawPathCache, points, () => getDrawStrokePath(shape, false)) return ( - + {shouldFill && ( { const sw = strokeWidth * 1.618 return ( - + { ): Partial { return this.transform(shape, bounds, info) } - - onSessionComplete(shape: DrawShape): Partial { - const bounds = this.getBounds(shape) - - const [x1, y1] = Vec.round(Vec.sub([bounds.minX, bounds.minY], shape.point)) - - const points = shape.points.map(([x0, y0, p]) => Vec.round([x0 - x1, y0 - y1]).concat(p)) - - return { - points, - point: Vec.add(shape.point, [x1, y1]), - } - } } const simulatePressureSettings = { diff --git a/packages/tldraw/src/shape/shapes/ellipse/ellipse.tsx b/packages/tldraw/src/shape/shapes/ellipse/ellipse.tsx index 16021e1f1..9217e630b 100644 --- a/packages/tldraw/src/shape/shapes/ellipse/ellipse.tsx +++ b/packages/tldraw/src/shape/shapes/ellipse/ellipse.tsx @@ -38,7 +38,7 @@ export class Ellipse extends TLDrawShapeUtil { } render = React.forwardRef>( - ({ shape, meta, isBinding, events }) => { + ({ shape, meta, isBinding, events }, ref) => { const { radius: [radiusX, radiusY], style, @@ -56,7 +56,7 @@ export class Ellipse extends TLDrawShapeUtil { ) return ( - + {isBinding && ( { const sw = strokeWidth * 1.618 return ( - + {isBinding && ( { } render = React.forwardRef>( - ({ shape, isBinding, isHovered, isSelected, events }) => { + ({ shape, isBinding, isHovered, isSelected, events }, ref) => { const { id, size } = shape const sw = 2 @@ -77,7 +77,7 @@ export class Group extends TLDrawShapeUtil { }) return ( - + {isBinding && ( { const styles = getShapeStyle(style, meta.isDarkMode) const strokeWidth = +styles.strokeWidth - React.useEffect(() => { - console.log(this.refMap.get(shape.id)) - }, []) - if (style.dash === DashStyle.Draw) { const pathData = Utils.getFromCache(this.pathCache, shape.size, () => renderPath(shape)) @@ -166,7 +162,6 @@ export class Rectangle extends TLDrawShapeUtil { } getBounds(shape: RectangleShape) { - console.log(this.refMap.get(shape.id)) const bounds = Utils.getFromCache(this.boundsCache, shape, () => { const [width, height] = shape.size return { diff --git a/packages/tldraw/src/state/session/sessions/draw/draw.session.ts b/packages/tldraw/src/state/session/sessions/draw/draw.session.ts index 603f9295b..71a03ad7e 100644 --- a/packages/tldraw/src/state/session/sessions/draw/draw.session.ts +++ b/packages/tldraw/src/state/session/sessions/draw/draw.session.ts @@ -8,10 +8,12 @@ import { TLDR } from '~state/tldr' export class DrawSession implements Session { id = 'draw' status = TLDrawStatus.Creating + topLeft: number[] origin: number[] previous: number[] last: number[] points: number[][] + shiftedPoints: number[][] = [] snapshot: DrawSnapshot isLocked?: boolean lockedDirection?: 'horizontal' | 'vertical' @@ -20,6 +22,7 @@ export class DrawSession implements Session { this.origin = point this.previous = point this.last = point + this.topLeft = point this.snapshot = getDrawSnapshot(data, id) @@ -79,6 +82,12 @@ export class DrawSession implements Session { // The previous input (not adjusted) point this.previous = point + const prevTopLeft = [...this.topLeft] + + this.topLeft = [Math.min(this.topLeft[0], point[0]), Math.min(this.topLeft[1], point[1])] + + const delta = Vec.sub(this.topLeft, this.origin) + // The new adjusted point const newPoint = Vec.round(Vec.sub(this.previous, this.origin)).concat(pressure) @@ -89,16 +98,35 @@ export class DrawSession implements Session { // The new adjusted point is now the previous adjusted point. this.last = newPoint + let points: number[][] + // Add the new adjusted point to the points array this.points.push(newPoint) + // Time to shift some points! + + if (Vec.isEqual(prevTopLeft, this.topLeft)) { + // If the new top left is the same as the previous top left, + // we don't need to shift anything: we just shift the new point + // and add it to the shifted points array. + points = [...this.shiftedPoints, Vec.sub(newPoint, delta)] + } else { + // If we have a new top left, then we need to iterate through + // the "unshifted" points array and shift them based on the + // offset between the new top left and the original top left. + points = this.points.map((pt) => Vec.sub(pt, delta)) + } + + this.shiftedPoints = points + return { document: { pages: { [data.appState.currentPageId]: { shapes: { [snapshot.id]: { - points: [...this.points], // Set to a new array here + point: this.topLeft, + points, }, }, }, @@ -163,11 +191,7 @@ export class DrawSession implements Session { pages: { [pageId]: { shapes: { - [snapshot.id]: TLDR.onSessionComplete( - data, - { ...TLDR.getShape(data, snapshot.id, pageId), points: [...this.points] }, - pageId - ), + [snapshot.id]: TLDR.getShape(data, snapshot.id, pageId), }, }, },