| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- import { Data } from "types"
- import * as vec from "utils/vec"
- import BaseSession from "./base-session"
- import commands from "state/commands"
- import { current } from "immer"
- import {
- getBoundsCenter,
- getCommonBounds,
- getPage,
- getSelectedShapes,
- getShapeBounds,
- } from "utils/utils"
-
- const PI2 = Math.PI * 2
-
- export default class RotateSession extends BaseSession {
- delta = [0, 0]
- origin: number[]
- snapshot: RotateSnapshot
-
- constructor(data: Data, point: number[]) {
- super(data)
- this.origin = point
- this.snapshot = getRotateSnapshot(data)
- }
-
- update(data: Data, point: number[], isLocked: boolean) {
- const { boundsCenter, shapes } = this.snapshot
-
- const page = getPage(data)
- const a1 = vec.angle(boundsCenter, this.origin)
- const a2 = vec.angle(boundsCenter, point)
-
- let rot = (PI2 + (a2 - a1)) % PI2
-
- if (isLocked) {
- rot = Math.floor((rot + Math.PI / 8) / (Math.PI / 4)) * (Math.PI / 4)
- }
-
- data.boundsRotation = (PI2 + (this.snapshot.boundsRotation + rot)) % PI2
-
- for (let { id, center, offset, rotation } of shapes) {
- const shape = page.shapes[id]
- shape.rotation = (PI2 + (rotation + rot)) % PI2
- const newCenter = vec.rotWith(center, boundsCenter, rot % PI2)
- shape.point = vec.sub(newCenter, offset)
- }
- }
-
- cancel(data: Data) {
- const page = getPage(data, this.snapshot.currentPageId)
-
- for (let { id, point, rotation } of this.snapshot.shapes) {
- const shape = page.shapes[id]
- shape.rotation = rotation
- shape.point = point
- }
- }
-
- complete(data: Data) {
- commands.rotate(data, this.snapshot, getRotateSnapshot(data))
- }
- }
-
- export function getRotateSnapshot(data: Data) {
- const shapes = getSelectedShapes(current(data))
-
- // A mapping of selected shapes and their bounds
- const shapesBounds = Object.fromEntries(
- shapes.map((shape) => [shape.id, getShapeBounds(shape)])
- )
-
- // The common (exterior) bounds of the selected shapes
- const bounds = getCommonBounds(...Object.values(shapesBounds))
-
- const boundsCenter = getBoundsCenter(bounds)
-
- return {
- boundsCenter,
- currentPageId: data.currentPageId,
- boundsRotation: data.boundsRotation,
- shapes: shapes.map(({ id, point, rotation }) => {
- const bounds = shapesBounds[id]
- const offset = [bounds.width / 2, bounds.height / 2]
- const center = getBoundsCenter(bounds)
-
- return {
- id,
- point,
- rotation,
- offset,
- center,
- }
- }),
- }
- }
-
- export type RotateSnapshot = ReturnType<typeof getRotateSnapshot>
|