[tiny] Slightly more efficient selection rotated page bounds / page bounds (#3178)

This PR makes a few tiny improvements to the way that selection page
bounds and rotated page bounds are calculated.

For bounds, we bail once we find a different rotation among the selected
shapes. Previously, we grabbed all of the rotations first before
comparing them; we only need to grab rotations until we find a rotation
that's different from the first one.

For rotating page bounds, we only look at the corners of the calculated
bounds, and we mutate the resulting points after we transform them.
Previously, we looked at all vertices and make a copy of the points when
rotating them. The transform already creates the copy, so we can mutate
it; and while the bounds are usually calculated from the vertices, using
the corners gives us fewer points to transform.

### Change Type

<!--  Please select a 'Scope' label ️ -->

- [x] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff

<!--  Please select a 'Type' label ️ -->

- [ ] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [x] `improvement` — Improving existing features
- [ ] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know


### Release Notes

- SDK, slightly more performant selection bounds calculations.
This commit is contained in:
Steve Ruiz 2024-03-17 13:24:32 +00:00 committed by GitHub
parent a9bc79b1c2
commit e764e59cda
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1647,19 +1647,24 @@ export class Editor extends EventEmitter<TLEventMap> {
*/
@computed getSelectionRotation(): number {
const selectedShapeIds = this.getSelectedShapeIds()
if (selectedShapeIds.length === 0) {
return 0
}
if (selectedShapeIds.length === 1) {
return this.getShapePageTransform(this.getSelectedShapeIds()[0])!.rotation()
let foundFirst = false // annoying but we can't use an i===0 check because we need to skip over undefineds
let rotation = 0
for (let i = 0, n = selectedShapeIds.length; i < n; i++) {
const pageTransform = this.getShapePageTransform(selectedShapeIds[i])
if (!pageTransform) continue
if (foundFirst) {
if (pageTransform.rotation() !== rotation) {
// There are at least 2 different rotations, so the common rotation is zero
return 0
}
} else {
// First rotation found
foundFirst = true
rotation = pageTransform.rotation()
}
}
const allRotations = selectedShapeIds.map((id) => this.getShapePageTransform(id)!.rotation())
// if the rotations are all compatible with each other, return the rotation of any one of them
if (allRotations.every((rotation) => Math.abs(rotation - allRotations[0]) < Math.PI / 180)) {
return this.getShapePageTransform(selectedShapeIds[0])!.rotation()
}
return 0
return rotation
}
/**
@ -1693,9 +1698,9 @@ export class Editor extends EventEmitter<TLEventMap> {
.flatMap((id) => {
const pageTransform = this.getShapePageTransform(id)
if (!pageTransform) return []
return pageTransform.applyToPoints(this.getShapeGeometry(id).vertices)
return pageTransform.applyToPoints(this.getShapeGeometry(id).bounds.corners)
})
.map((p) => Vec.Rot(p, -selectionRotation))
.map((p) => p.rot(-selectionRotation))
)
// now position box so that it's top-left corner is in the right place
boxFromRotatedVertices.point = boxFromRotatedVertices.point.rot(selectionRotation)