62 lines
1.8 KiB
TypeScript
62 lines
1.8 KiB
TypeScript
export interface NormalizedHudPosition {
|
|
readonly x: number;
|
|
readonly y: number;
|
|
}
|
|
|
|
export interface HudSize {
|
|
readonly width: number;
|
|
readonly height: number;
|
|
}
|
|
|
|
export const DEFAULT_THREAT_METER_POSITION: NormalizedHudPosition = Object.freeze({
|
|
x: 0.78,
|
|
y: 0.18,
|
|
});
|
|
|
|
function finite(value: number, fallback: number): number {
|
|
return Number.isFinite(value) ? value : fallback;
|
|
}
|
|
|
|
function clamp(value: number, minimum: number, maximum: number): number {
|
|
return Math.max(minimum, Math.min(maximum, value));
|
|
}
|
|
|
|
export function normalizeHudPosition(
|
|
value: unknown,
|
|
fallback: NormalizedHudPosition = DEFAULT_THREAT_METER_POSITION,
|
|
): NormalizedHudPosition {
|
|
if (!value || typeof value !== "object") return fallback;
|
|
const candidate = value as Partial<NormalizedHudPosition>;
|
|
return {
|
|
x: clamp(finite(candidate.x ?? Number.NaN, fallback.x), 0, 1),
|
|
y: clamp(finite(candidate.y ?? Number.NaN, fallback.y), 0, 1),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Keeps a center-anchored HUD panel inside the visible viewport. Positions are
|
|
* normalized so a saved desktop location remains meaningful on smaller screens.
|
|
*/
|
|
export function clampHudPositionToViewport(
|
|
position: NormalizedHudPosition,
|
|
viewport: HudSize,
|
|
panel: HudSize,
|
|
padding = 6,
|
|
): NormalizedHudPosition {
|
|
const viewportWidth = Math.max(1, finite(viewport.width, 1));
|
|
const viewportHeight = Math.max(1, finite(viewport.height, 1));
|
|
const horizontalInset = Math.min(
|
|
0.5,
|
|
(Math.max(0, finite(panel.width, 0)) / 2 + Math.max(0, padding)) / viewportWidth,
|
|
);
|
|
const verticalInset = Math.min(
|
|
0.5,
|
|
(Math.max(0, finite(panel.height, 0)) / 2 + Math.max(0, padding)) / viewportHeight,
|
|
);
|
|
const normalized = normalizeHudPosition(position);
|
|
return {
|
|
x: clamp(normalized.x, horizontalInset, 1 - horizontalInset),
|
|
y: clamp(normalized.y, verticalInset, 1 - verticalInset),
|
|
};
|
|
}
|