Merge branch 'main' into dependabot/npm_and_yarn/npm_and_yarn-9e0581ad53

pull/3505/head
Steve Ruiz 2024-04-21 13:34:01 +01:00 zatwierdzone przez GitHub
commit 4fce838cda
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
7 zmienionych plików z 2385 dodań i 61 usunięć

Wyświetl plik

@ -97,7 +97,7 @@ export class Drawing extends StateNode {
this.mergeNextPoint = false
}
this.updateShapes()
this.updateDrawingShape()
}
}
@ -115,7 +115,7 @@ export class Drawing extends StateNode {
}
}
}
this.updateShapes()
this.updateDrawingShape()
}
override onKeyUp: TLEventHandlers['onKeyUp'] = (info) => {
@ -137,7 +137,7 @@ export class Drawing extends StateNode {
}
}
this.updateShapes()
this.updateDrawingShape()
}
override onExit? = () => {
@ -281,7 +281,7 @@ export class Drawing extends StateNode {
this.initialShape = this.editor.getShape<DrawableShape>(id)
}
private updateShapes() {
private updateDrawingShape() {
const { initialShape } = this
const { inputs } = this.editor

Wyświetl plik

@ -1,12 +1,4 @@
import {
Vec,
VecLike,
assert,
average,
precise,
shortAngleDist,
toDomPrecision,
} from '@tldraw/editor'
import { Vec, VecLike, assert, average, precise, toDomPrecision } from '@tldraw/editor'
import { getStrokeOutlineTracks } from './getStrokeOutlinePoints'
import { getStrokePoints } from './getStrokePoints'
import { setStrokePointRadii } from './setStrokePointRadii'
@ -36,17 +28,20 @@ function partitionAtElbows(points: StrokePoint[]): StrokePoint[][] {
const result: StrokePoint[][] = []
let currentPartition: StrokePoint[] = [points[0]]
for (let i = 1; i < points.length - 1; i++) {
const prevPoint = points[i - 1]
const thisPoint = points[i]
const nextPoint = points[i + 1]
const prevAngle = Vec.Angle(prevPoint.point, thisPoint.point)
const nextAngle = Vec.Angle(thisPoint.point, nextPoint.point)
// acuteness is a normalized representation of how acute the angle is.
// 1 is an infinitely thin wedge
// 0 is a straight line
const acuteness = Math.abs(shortAngleDist(prevAngle, nextAngle)) / Math.PI
if (acuteness > 0.8) {
let prevV = Vec.Sub(points[1].point, points[0].point).uni()
let nextV: Vec
let dpr: number
let prevPoint: StrokePoint, thisPoint: StrokePoint, nextPoint: StrokePoint
for (let i = 1, n = points.length; i < n - 1; i++) {
prevPoint = points[i - 1]
thisPoint = points[i]
nextPoint = points[i + 1]
nextV = Vec.Sub(nextPoint.point, thisPoint.point).uni()
dpr = Vec.Dpr(prevV, nextV)
prevV = nextV
if (dpr < -0.8) {
// always treat such acute angles as elbows
// and use the extended .input point as the elbow point for swooshiness in fast zaggy lines
const elbowPoint = {
@ -59,19 +54,20 @@ function partitionAtElbows(points: StrokePoint[]): StrokePoint[][] {
continue
}
currentPartition.push(thisPoint)
if (acuteness < 0.25) {
// this is not an elbow, bail out
if (dpr > 0.7) {
// Not an elbow
continue
}
// so now we have a reasonably acute angle but it might not be an elbow if it's far
// away from it's neighbors
const avgRadius = (prevPoint.radius + thisPoint.radius + nextPoint.radius) / 3
const incomingNormalizedDist = Vec.Dist(prevPoint.point, thisPoint.point) / avgRadius
const outgoingNormalizedDist = Vec.Dist(thisPoint.point, nextPoint.point) / avgRadius
// angular dist is a normalized representation of how far away the point is from it's neighbors
// away from it's neighbors, angular dist is a normalized representation of how far away the point is from it's neighbors
// (normalized by the radius)
const angularDist = incomingNormalizedDist + outgoingNormalizedDist
if (angularDist < 1.5) {
if (
(Vec.Dist2(prevPoint.point, thisPoint.point) + Vec.Dist2(thisPoint.point, nextPoint.point)) /
((prevPoint.radius + thisPoint.radius + nextPoint.radius) / 3) ** 2 <
1.5
) {
// if this point is kinda close to its neighbors and it has a reasonably
// acute angle, it's probably a hard elbow
currentPartition.push(thisPoint)
@ -89,11 +85,13 @@ function partitionAtElbows(points: StrokePoint[]): StrokePoint[][] {
function cleanUpPartition(partition: StrokePoint[]) {
// clean up start of partition (remove points that are too close to the start)
const startPoint = partition[0]
let nextPoint: StrokePoint
while (partition.length > 2) {
const nextPoint = partition[1]
const dist = Vec.Dist(startPoint.point, nextPoint.point)
const avgRadius = (startPoint.radius + nextPoint.radius) / 2
if (dist < avgRadius * 0.5) {
nextPoint = partition[1]
if (
Vec.Dist2(startPoint.point, nextPoint.point) <
(((startPoint.radius + nextPoint.radius) / 2) * 0.5) ** 2
) {
partition.splice(1, 1)
} else {
break
@ -101,11 +99,13 @@ function cleanUpPartition(partition: StrokePoint[]) {
}
// clean up end of partition in the same fashion
const endPoint = partition[partition.length - 1]
let prevPoint: StrokePoint
while (partition.length > 2) {
const prevPoint = partition[partition.length - 2]
const dist = Vec.Dist(endPoint.point, prevPoint.point)
const avgRadius = (endPoint.radius + prevPoint.radius) / 2
if (dist < avgRadius * 0.5) {
prevPoint = partition[partition.length - 2]
if (
Vec.Dist2(endPoint.point, prevPoint.point) <
(((endPoint.radius + prevPoint.radius) / 2) * 0.5) ** 2
) {
partition.splice(partition.length - 2, 1)
} else {
break
@ -115,13 +115,14 @@ function cleanUpPartition(partition: StrokePoint[]) {
if (partition.length > 1) {
partition[0] = {
...partition[0],
vector: Vec.FromAngle(Vec.Angle(partition[1].point, partition[0].point)),
vector: Vec.Sub(partition[0].point, partition[1].point).uni(),
}
partition[partition.length - 1] = {
...partition[partition.length - 1],
vector: Vec.FromAngle(
Vec.Angle(partition[partition.length - 1].point, partition[partition.length - 2].point)
),
vector: Vec.Sub(
partition[partition.length - 2].point,
partition[partition.length - 1].point
).uni(),
}
}
return partition

Wyświetl plik

@ -9,6 +9,8 @@ import {
TLTextShape,
VecLike,
isNonNull,
preventDefault,
stopEventPropagation,
uniq,
useEditor,
useValue,
@ -615,24 +617,29 @@ export function useNativeClipboardEvents() {
useEffect(() => {
if (!appIsFocused) return
const copy = () => {
const copy = (e: ClipboardEvent) => {
if (
editor.getSelectedShapeIds().length === 0 ||
editor.getEditingShapeId() !== null ||
disallowClipboardEvents(editor)
)
) {
return
}
preventDefault(e)
handleNativeOrMenuCopy(editor)
trackEvent('copy', { source: 'kbd' })
}
function cut() {
function cut(e: ClipboardEvent) {
if (
editor.getSelectedShapeIds().length === 0 ||
editor.getEditingShapeId() !== null ||
disallowClipboardEvents(editor)
)
) {
return
}
preventDefault(e)
handleNativeOrMenuCopy(editor)
editor.deleteShapes(editor.getSelectedShapeIds())
trackEvent('cut', { source: 'kbd' })
@ -648,9 +655,9 @@ export function useNativeClipboardEvents() {
}
}
const paste = (event: ClipboardEvent) => {
const paste = (e: ClipboardEvent) => {
if (disablingMiddleClickPaste) {
event.stopPropagation()
stopEventPropagation(e)
return
}
@ -660,8 +667,8 @@ export function useNativeClipboardEvents() {
if (editor.getEditingShapeId() !== null || disallowClipboardEvents(editor)) return
// First try to use the clipboard data on the event
if (event.clipboardData && !editor.inputs.shiftKey) {
handlePasteFromEventClipboardData(editor, event.clipboardData)
if (e.clipboardData && !editor.inputs.shiftKey) {
handlePasteFromEventClipboardData(editor, e.clipboardData)
} else {
// Or else use the clipboard API
navigator.clipboard.read().then((clipboardItems) => {
@ -671,6 +678,7 @@ export function useNativeClipboardEvents() {
})
}
preventDefault(e)
trackEvent('paste', { source: 'kbd' })
}

Wyświetl plik

@ -1,5 +1,6 @@
import { TLDrawShape, TLHighlightShape, last } from '@tldraw/editor'
import { TestEditor } from './TestEditor'
import { TEST_DRAW_SHAPE_SCREEN_POINTS } from './drawing.data'
jest.useFakeTimers()
@ -260,3 +261,22 @@ for (const toolType of ['draw', 'highlight'] as const) {
})
})
}
it('Draws a bunch', () => {
editor.setCurrentTool('draw').setCamera({ x: 0, y: 0, z: 1 })
const [first, ...rest] = TEST_DRAW_SHAPE_SCREEN_POINTS
editor.pointerMove(first.x, first.y).pointerDown()
for (const point of rest) {
editor.pointerMove(point.x, point.y)
}
editor.pointerUp()
editor.selectAll()
const shape = { ...editor.getLastCreatedShape() }
// @ts-expect-error
delete shape.id
expect(shape).toMatchSnapshot('draw shape')
})

Wyświetl plik

@ -34,15 +34,17 @@ export function measureAverageDuration(
const start = performance.now()
const result = originalMethod.apply(this, args)
const end = performance.now()
const value = averages.get(descriptor.value)!
const length = end - start
const total = value.total + length
const count = value.count + 1
averages.set(descriptor.value, { total, count })
// eslint-disable-next-line no-console
console.log(
`${propertyKey} took ${(end - start).toFixed(2)}ms | average ${(total / count).toFixed(2)}ms`
)
if (length !== 0) {
const value = averages.get(descriptor.value)!
const total = value.total + length
const count = value.count + 1
averages.set(descriptor.value, { total, count })
// eslint-disable-next-line no-console
console.log(
`${propertyKey} took ${(end - start).toFixed(2)}ms | average ${(total / count).toFixed(2)}ms`
)
}
return result
}
averages.set(descriptor.value, { total: 0, count: 0 })