diff --git a/lib/shapes/ellipse.tsx b/lib/shapes/ellipse.tsx index df7b4e2d3..e4fba1a0f 100644 --- a/lib/shapes/ellipse.tsx +++ b/lib/shapes/ellipse.tsx @@ -73,6 +73,8 @@ const ellipse = createShape({ }, hitTestBounds(this, shape, brushBounds) { + // TODO: Account for rotation + const shapeBounds = this.getBounds(shape) return ( diff --git a/lib/shapes/index.tsx b/lib/shapes/index.tsx index 2032d9b32..f997f0ac7 100644 --- a/lib/shapes/index.tsx +++ b/lib/shapes/index.tsx @@ -61,11 +61,13 @@ export interface ShapeUtility { bounds: Bounds, info: { type: TransformEdge | TransformCorner + boundsRotation: number initialShape: K initialShapeBounds: BoundsSnapshot initialBounds: Bounds isFlippedX: boolean isFlippedY: boolean + isSingle: boolean anchor: TransformEdge | TransformCorner } ): K diff --git a/lib/shapes/rectangle.tsx b/lib/shapes/rectangle.tsx index 4d2dd6f69..265a1866e 100644 --- a/lib/shapes/rectangle.tsx +++ b/lib/shapes/rectangle.tsx @@ -103,9 +103,44 @@ const rectangle = createShape({ return shape }, - transform(shape, bounds) { - shape.point = [bounds.minX, bounds.minY] - shape.size = [bounds.width, bounds.height] + transform( + shape, + shapeBounds, + { initialShape, isSingle, initialShapeBounds, isFlippedX, isFlippedY } + ) { + // TODO: Apply rotation to single-selection items + + if (shape.rotation === 0 || isSingle) { + shape.size = [shapeBounds.width, shapeBounds.height] + shape.point = [shapeBounds.minX, shapeBounds.minY] + } else { + shape.size = vec.mul( + initialShape.size, + Math.min( + shapeBounds.width / initialShapeBounds.width, + shapeBounds.height / initialShapeBounds.height + ) + ) + + const newCenter = [ + shapeBounds.minX + shapeBounds.width / 2, + shapeBounds.minY + shapeBounds.height / 2, + ] + + shape.point = vec.sub(newCenter, vec.div(shape.size, 2)) + } + + // Rotation for flipped shapes + + shape.rotation = initialShape.rotation + + if (isFlippedX) { + shape.rotation *= -1 + } + + if (isFlippedY) { + shape.rotation *= -1 + } return shape }, diff --git a/state/commands/transform.ts b/state/commands/transform.ts index b86da063d..ebe48d5c2 100644 --- a/state/commands/transform.ts +++ b/state/commands/transform.ts @@ -22,6 +22,8 @@ export default function translateCommand( initialBounds, currentPageId, selectedIds, + isSingle, + boundsRotation, } = after const { shapes } = data.document.pages[currentPageId] @@ -35,8 +37,10 @@ export default function translateCommand( initialShape, initialShapeBounds, initialBounds, + boundsRotation, isFlippedX: false, isFlippedY: false, + isSingle, anchor, }) }) @@ -48,6 +52,8 @@ export default function translateCommand( initialBounds, currentPageId, selectedIds, + isSingle, + boundsRotation, } = before const { shapes } = data.document.pages[currentPageId] @@ -61,8 +67,10 @@ export default function translateCommand( initialShape, initialShapeBounds, initialBounds, + boundsRotation, isFlippedX: false, isFlippedY: false, + isSingle, anchor: type, }) }) diff --git a/state/sessions/transform-session.ts b/state/sessions/transform-session.ts index 77d8c56a5..886f2238e 100644 --- a/state/sessions/transform-session.ts +++ b/state/sessions/transform-session.ts @@ -32,6 +32,18 @@ export default class TransformSession extends BaseSession { super(data) this.origin = point this.transformType = transformType + + // if (data.selectedIds.size === 1) { + // const shape = + // data.document.pages[data.currentPageId].shapes[ + // Array.from(data.selectedIds.values())[0] + // ] + + // if (shape.rotation > 0) { + + // } + // } + this.snapshot = getTransformSnapshot(data, transformType) const { minX, minY, maxX, maxY } = this.snapshot.initialBounds @@ -43,21 +55,26 @@ export default class TransformSession extends BaseSession { } update(data: Data, point: number[]) { - const { shapeBounds, initialBounds, currentPageId, selectedIds } = - this.snapshot - - const { shapes } = data.document.pages[currentPageId] - - const delta = vec.vec(this.origin, point) - const { corners: { a, b }, transformType, } = this - // Edge Transform + const { + boundsRotation, + shapeBounds, + initialBounds, + currentPageId, + selectedIds, + isSingle, + } = this.snapshot + + const { shapes } = data.document.pages[currentPageId] + + const delta = vec.vec(this.origin, point) + /* - Edge transform + Transforms Corners a and b are the original top-left and bottom-right corners of the bounding box. Depending on what the user is dragging, change one or both @@ -153,8 +170,10 @@ export default class TransformSession extends BaseSession { initialShape, initialShapeBounds, initialBounds, + boundsRotation, isFlippedX: this.isFlippedX, isFlippedY: this.isFlippedY, + isSingle, anchor: getTransformAnchor( this.transformType, this.isFlippedX, @@ -165,8 +184,14 @@ export default class TransformSession extends BaseSession { } cancel(data: Data) { - const { shapeBounds, initialBounds, currentPageId, selectedIds } = - this.snapshot + const { + shapeBounds, + boundsRotation, + initialBounds, + currentPageId, + selectedIds, + isSingle, + } = this.snapshot const { shapes } = data.document.pages[currentPageId] @@ -180,8 +205,10 @@ export default class TransformSession extends BaseSession { initialShape, initialShapeBounds, initialBounds, + boundsRotation, isFlippedX: false, isFlippedY: false, + isSingle, anchor: getTransformAnchor(this.transformType, false, false), }) }) @@ -205,6 +232,7 @@ export function getTransformSnapshot( document: { pages }, selectedIds, currentPageId, + boundsRotation, } = current(data) const pageShapes = pages[currentPageId].shapes @@ -226,6 +254,8 @@ export function getTransformSnapshot( currentPageId, type: transformType, initialBounds: bounds, + boundsRotation, + isSingle: selectedIds.size === 1, selectedIds: new Set(selectedIds), shapeBounds: Object.fromEntries( Array.from(selectedIds.values()).map((id) => {