import type { Graphics } from 'pixi.js'; import type { VectorPoint } from '../core/model/Asset'; import type { Vec2 } from '../core/model/Properties'; import { handleAt } from '../core/model/vectorart'; import { Theme } from '../ui'; /** Side of a point handle in screen pixels – constant, so a point stays grabbable at any zoom. */ export const POINT_SIZE = 8; /** Radius of a Bezier handle's knob, in screen pixels. */ export const HANDLE_RADIUS = 4; /** Pixels the pointer must travel before a press becomes a drag rather than a click. */ export const DRAG_THRESHOLD = 3; /** * One point of a Vector art ring or a curve with its handles, in widget pixels so they keep their * size; `toLocal` says where a place in the picture is drawn. */ export function drawPointGrip( g: Graphics, point: VectorPoint, picked: boolean, toLocal: (x: number, y: number) => Vec2, ): void { const at = toLocal(point.x, point.y); for (const side of ['in', 'out'] as const) { const handle = handleAt(point, side); if (!handle) continue; const tip = toLocal(handle.x, handle.y); g.moveTo(at.x, at.y).lineTo(tip.x, tip.y).stroke({ width: 1, color: Theme.colors.marquee }); g.circle(tip.x, tip.y, HANDLE_RADIUS) .fill(Theme.colors.viewport) .stroke({ width: 1, color: Theme.colors.marquee }); } const half = POINT_SIZE / 2; g.rect(at.x - half, at.y - half, POINT_SIZE, POINT_SIZE) .fill(picked ? Theme.colors.accent : Theme.colors.accentText) .stroke({ width: 1, color: picked ? Theme.colors.accentText : Theme.colors.accent }); }