fledgling/src/layout.ts

91 lines
2.5 KiB
TypeScript

import { AlignX, AlignY, Point, Rect, Size } from "./engine/datatypes.ts";
import { D } from "./engine/public.ts";
import { getHud } from "./hud.ts";
import { getHotbar } from "./hotbar.ts";
// general
let margin = 8;
export function getLayoutRect(
size: Size,
options?: { alignX?: AlignX; alignY?: AlignY },
): Rect {
let { w: screenW, h: screenH } = D.size;
// first of all: place the _internal_ screen inside the real screen
let marginalScreenW = screenW - margin * 2;
let marginalScreenH = screenH - margin * 2;
let marginalScreenX = margin;
let marginalScreenY = margin;
// NOTE: If the screen is too small, remainingSpace will be negative
// This is fine -- it actually results in reasonable outcomes except
// that the size of the box is exceeded in the opposite of the align direction.
let { w: innerW, h: innerH } = size;
let remainingSpaceX = marginalScreenW - innerW;
let remainingSpaceY = marginalScreenH - innerH;
let alignXCoef =
options?.alignX == AlignX.Left
? 0.0
: options?.alignX == AlignX.Center
? 0.5
: options?.alignX == AlignX.Right
? 1.0
: 0.5;
let alignYCoef =
options?.alignY == AlignY.Top
? 0.0
: options?.alignY == AlignY.Middle
? 0.5
: options?.alignY == AlignY.Bottom
? 1.0
: 0.5;
let x = marginalScreenX + alignXCoef * remainingSpaceX;
let y = marginalScreenY + alignYCoef * remainingSpaceY;
return new Rect(new Point(Math.floor(x), Math.floor(y)), size);
}
export function withCamera(part: UIPart, cb: () => void) {
let region = getPartLocation(part);
D.withCamera(D.camera.offset(region.top.negate()), cb);
}
// specific
export type UIPart =
| "BottomModal"
| "FullscreenPopover"
| "Hotbar"
| "HUD"
| "Gameplay"
| "Thralls";
export function getPartLocation(part: UIPart) {
switch (part) {
case "BottomModal":
return getLayoutRect(new Size(384, 128), {
alignX: AlignX.Center,
alignY: AlignY.Bottom,
});
case "FullscreenPopover":
return getLayoutRect(new Size(384, 384));
case "Gameplay":
case "Thralls":
return getLayoutRect(new Size(384, 384));
case "Hotbar":
return getLayoutRect(getHotbar().size, {
alignX: AlignX.Center,
alignY: AlignY.Bottom,
});
case "HUD":
return getLayoutRect(getHud().size, {
alignX: AlignX.Left,
alignY: AlignY.Top,
});
}
throw `not sure what layout rect to use ${part}`;
}