import type { Vec2D } from "@core/geometry"; import type { Command } from "./command"; import { commandIds } from "./ids"; export type ViewportPanPayload = { delta: Vec2D; }; export type ViewportSetZoomPayload = { zoom: number; }; export type ViewportZoomAroundPointPayload = { zoom: number; point: Vec2D; }; export type ViewportSetSizePayload = { w: number; h: number; }; export const viewportPanCommand: Command = { id: commandIds.viewportPan, name: "Pan viewport", execute({ state }, payload) { return { ...state, editor: { ...state.editor, viewport: { ...state.editor.viewport, center: { x: state.editor.viewport.center.x + payload.delta.x, y: state.editor.viewport.center.y + payload.delta.y, }, }, }, }; }, }; export const viewportSetZoomCommand: Command = { id: commandIds.viewportSetZoom, name: "Set viewport zoom", execute({ state }, payload) { const zoom = Math.max(0.01, payload.zoom); return { ...state, editor: { ...state.editor, viewport: { ...state.editor.viewport, zoom, }, }, }; }, }; export const viewportZoomAroundPointCommand: Command = { id: commandIds.viewportZoomAroundPoint, name: "Zoom viewport around point", execute({ state }, payload) { const viewport = state.editor.viewport; const zoom = Math.max(0.01, payload.zoom); const offset = { x: payload.point.x - viewport.size.w / 2, y: payload.point.y - viewport.size.h / 2, }; const documentPoint = { x: viewport.center.x + offset.x / viewport.zoom, y: viewport.center.y + offset.y / viewport.zoom, }; return { ...state, editor: { ...state.editor, viewport: { ...viewport, zoom, center: { x: documentPoint.x - offset.x / zoom, y: documentPoint.y - offset.y / zoom, }, }, }, }; }, }; export const viewportSetSizeCommand: Command = { id: commandIds.viewportSetSize, name: "Set viewport size", execute({ state }, payload) { return { ...state, editor: { ...state.editor, viewport: { ...state.editor.viewport, size: { w: Math.max(0, payload.w), h: Math.max(0, payload.h), }, }, }, }; }, }; export const viewportResetCommand: Command = { id: commandIds.viewportReset, name: "Reset viewport", execute({ state }) { return { ...state, editor: { ...state.editor, viewport: { center: { x: 0, y: 0 }, zoom: 1, rotation: 0, size: state.editor.viewport.size, }, }, }; }, }; export const viewportCommands = [ viewportPanCommand, viewportSetZoomCommand, viewportZoomAroundPointCommand, viewportSetSizeCommand, viewportResetCommand, ] satisfies Command[];