Files
picoGraph/scripts/ui/workspace/WorkspaceGeometry.js
Max Litruv Boonzaayer f917cf6ad5 Add initial Pico-8 cartridges for testing
- Created test_cart.p8 with basic drawing functionality and a print statement.
- Created test_unix.p8 with a simple initialization function.
2026-03-21 18:38:43 +11:00

78 lines
2.8 KiB
JavaScript

import { DEFAULT_GRID_SIZE } from "../BlueprintWorkspaceConstants.js";
/**
* Provides workspace geometry helpers for coordinate conversion and transforms.
*/
export class WorkspaceGeometry {
/**
* Resolves the active grid size from workspace styles.
*
* @param {import('../BlueprintWorkspace.js').BlueprintWorkspace} workspace Workspace instance.
* @returns {number}
*/
static resolveGridSize(workspace) {
const { workspaceElement } = workspace;
if (!workspaceElement || !workspaceElement.isConnected) {
return DEFAULT_GRID_SIZE;
}
const computed = window.getComputedStyle(workspaceElement);
const raw = computed.getPropertyValue("--grid-size");
const parsed = Number.parseFloat(raw);
if (Number.isFinite(parsed) && parsed > 0) {
return parsed;
}
return DEFAULT_GRID_SIZE;
}
/**
* Converts viewport coordinates into workspace-relative coordinates.
*
* @param {import('../BlueprintWorkspace.js').BlueprintWorkspace} workspace Workspace instance.
* @param {{ clientX?: number, clientY?: number }} event Pointer-like event payload.
* @returns {{ x: number, y: number }}
*/
static eventToWorkspacePoint(workspace, event) {
return workspace.dragManager.clientToWorkspace(event?.clientX, event?.clientY);
}
/**
* Snaps a workspace position to the configured grid size.
*
* @param {import('../BlueprintWorkspace.js').BlueprintWorkspace} workspace Workspace instance.
* @param {{ x: number, y: number }} position Raw workspace position.
* @returns {{ x: number, y: number }}
*/
static snapPositionToGrid(workspace, position) {
const size = workspace.gridSize || DEFAULT_GRID_SIZE;
const effectiveOffset = workspace.navigationManager?.getEffectiveOffset?.();
const offsetX = Number.isFinite(effectiveOffset?.x) ? effectiveOffset.x : 0;
const offsetY = Number.isFinite(effectiveOffset?.y) ? effectiveOffset.y : 0;
const snap = (value, offset) => {
const local = value - offset;
const snapped = Math.round(local / size) * size;
return snapped + offset;
};
return { x: snap(position.x, offsetX), y: snap(position.y, offsetY) };
}
/**
* Converts a position vector into a CSS transform.
*
* @param {{x:number,y:number}} position Position vector.
* @param {number} rotation Rotation in degrees around the Z axis.
* @returns {string}
*/
static positionToTransform(position, rotation = 0) {
const transforms = [`translate3d(${position.x}px, ${position.y}px, 0)`];
const rotationZ = Number.isFinite(rotation) ? rotation : 0;
if (rotationZ) {
const tilt = Math.max(-10, Math.min(10, rotationZ * 0.8));
transforms.push(`rotate3d(0, 1, 0, ${tilt}deg)`);
transforms.push(`rotate(${rotationZ}deg)`);
}
return transforms.join(" ");
}
}