{ "version": 3, "sources": ["../../../../../src/lib/tools/SelectTool/children/Rotating.ts"], "sourcesContent": ["import {\n\tEPSILON,\n\tRotateCorner,\n\tStateNode,\n\tTLEventHandlers,\n\tTLPointerEventInfo,\n\tTLRotationSnapshot,\n\tangleDelta,\n\tapplyRotationToSnapshotShapes,\n\tdegreesToRadians,\n\tgetRotationSnapshot,\n\tsnapAngle,\n} from '@tldraw/editor'\nimport { CursorTypeMap } from './PointingResizeHandle'\n\nexport class Rotating extends StateNode {\n\tstatic override id = 'rotating'\n\n\tsnapshot = {} as TLRotationSnapshot\n\n\tinfo = {} as Extract & { onInteractionEnd?: string }\n\n\tmarkId = ''\n\n\toverride onEnter = (\n\t\tinfo: TLPointerEventInfo & { target: 'selection'; onInteractionEnd?: string }\n\t) => {\n\t\t// Store the event information\n\t\tthis.info = info\n\t\tthis.parent.currentToolIdMask = info.onInteractionEnd\n\n\t\tthis.markId = 'rotate start'\n\t\tthis.editor.mark(this.markId)\n\n\t\tconst snapshot = getRotationSnapshot({ editor: this.editor })\n\t\tif (!snapshot) return this.parent.transition('idle', this.info)\n\t\tthis.snapshot = snapshot\n\n\t\t// Trigger a pointer move\n\t\tthis.handleStart()\n\t}\n\n\toverride onExit = () => {\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t\tthis.parent.currentToolIdMask = undefined\n\n\t\tthis.snapshot = {} as TLRotationSnapshot\n\t}\n\n\toverride onPointerMove = () => {\n\t\tthis.update()\n\t}\n\n\toverride onKeyDown = () => {\n\t\tthis.update()\n\t}\n\n\toverride onKeyUp = () => {\n\t\tthis.update()\n\t}\n\n\toverride onPointerUp: TLEventHandlers['onPointerUp'] = () => {\n\t\tthis.complete()\n\t}\n\n\toverride onComplete: TLEventHandlers['onComplete'] = () => {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel = () => {\n\t\tthis.cancel()\n\t}\n\n\t// ---\n\n\tprivate update = () => {\n\t\tconst newSelectionRotation = this._getRotationFromPointerPosition({\n\t\t\tsnapToNearestDegree: false,\n\t\t})\n\n\t\tapplyRotationToSnapshotShapes({\n\t\t\teditor: this.editor,\n\t\t\tdelta: newSelectionRotation,\n\t\t\tsnapshot: this.snapshot,\n\t\t\tstage: 'update',\n\t\t})\n\n\t\t// Update cursor\n\t\tthis.editor.updateInstanceState({\n\t\t\tcursor: {\n\t\t\t\ttype: CursorTypeMap[this.info.handle as RotateCorner],\n\t\t\t\trotation: newSelectionRotation + this.snapshot.initialSelectionRotation,\n\t\t\t},\n\t\t})\n\t}\n\n\tprivate cancel = () => {\n\t\tthis.editor.bailToMark(this.markId)\n\t\tif (this.info.onInteractionEnd) {\n\t\t\tthis.editor.setCurrentTool(this.info.onInteractionEnd, this.info)\n\t\t} else {\n\t\t\tthis.parent.transition('idle', this.info)\n\t\t}\n\t}\n\n\tprivate complete = () => {\n\t\tapplyRotationToSnapshotShapes({\n\t\t\teditor: this.editor,\n\t\t\tdelta: this._getRotationFromPointerPosition({ snapToNearestDegree: true }),\n\t\t\tsnapshot: this.snapshot,\n\t\t\tstage: 'end',\n\t\t})\n\t\tif (this.info.onInteractionEnd) {\n\t\t\tthis.editor.setCurrentTool(this.info.onInteractionEnd, this.info)\n\t\t} else {\n\t\t\tthis.parent.transition('idle', this.info)\n\t\t}\n\t}\n\n\tprotected handleStart() {\n\t\tconst newSelectionRotation = this._getRotationFromPointerPosition({\n\t\t\tsnapToNearestDegree: false,\n\t\t})\n\n\t\tapplyRotationToSnapshotShapes({\n\t\t\teditor: this.editor,\n\t\t\tdelta: this._getRotationFromPointerPosition({ snapToNearestDegree: false }),\n\t\t\tsnapshot: this.snapshot,\n\t\t\tstage: 'start',\n\t\t})\n\n\t\t// Update cursor\n\t\tthis.editor.updateInstanceState({\n\t\t\tcursor: {\n\t\t\t\ttype: CursorTypeMap[this.info.handle as RotateCorner],\n\t\t\t\trotation: newSelectionRotation + this.snapshot.initialSelectionRotation,\n\t\t\t},\n\t\t})\n\t}\n\n\t_getRotationFromPointerPosition({ snapToNearestDegree }: { snapToNearestDegree: boolean }) {\n\t\tconst {\n\t\t\tselectionRotatedPageBounds: selectionBounds,\n\t\t\tselectionRotation,\n\t\t\tinputs: { shiftKey, currentPagePoint },\n\t\t} = this.editor\n\t\tconst { initialCursorAngle, initialSelectionRotation } = this.snapshot\n\n\t\tif (!selectionBounds) return initialSelectionRotation\n\n\t\tconst selectionPageCenter = selectionBounds.center\n\t\t\t.clone()\n\t\t\t.rotWith(selectionBounds.point, selectionRotation)\n\n\t\t// The delta is the difference between the current angle and the initial angle\n\t\tconst preSnapRotationDelta = selectionPageCenter.angle(currentPagePoint) - initialCursorAngle\n\t\tlet newSelectionRotation = initialSelectionRotation + preSnapRotationDelta\n\n\t\tif (shiftKey) {\n\t\t\tnewSelectionRotation = snapAngle(newSelectionRotation, 24)\n\t\t} else if (snapToNearestDegree) {\n\t\t\tnewSelectionRotation = Math.round(newSelectionRotation / EPSILON) * EPSILON\n\n\t\t\tif (this.editor.instanceState.isCoarsePointer) {\n\t\t\t\tconst snappedToRightAngle = snapAngle(newSelectionRotation, 4)\n\t\t\t\tconst angleToRightAngle = angleDelta(newSelectionRotation, snappedToRightAngle)\n\t\t\t\tif (Math.abs(angleToRightAngle) < degreesToRadians(5)) {\n\t\t\t\t\tnewSelectionRotation = snappedToRightAngle\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn newSelectionRotation - initialSelectionRotation\n\t}\n}\n"], "mappings": "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", "names": [] }