import { describe, expect, it } from "vitest"; import { applyRadialDeadzone, cameraRelativeMovement, cameraYawAfterHorizontalLook, clampCameraPitch, DEFAULT_CAMERA_PITCH, normalizePlanar, wrapAngle, } from "./inputMath"; describe("input math", () => { it("removes stick drift and remaps motion outside the deadzone", () => { expect(applyRadialDeadzone(0.08, -0.05)).toEqual([0, 0]); const [x, y] = applyRadialDeadzone(0.59, 0); expect(x).toBeCloseTo(0.5, 2); expect(y).toBe(0); }); it("caps diagonal movement at unit length", () => { const [x, z] = normalizePlanar(1, 1); expect(Math.hypot(x, z)).toBeCloseTo(1); }); it("rotates +Z-forward movement by camera yaw", () => { expect(cameraRelativeMovement(0, 1, 0)).toEqual([0, 1]); const [x, z] = cameraRelativeMovement(0, 1, -Math.PI / 2); expect(x).toBeCloseTo(-1); expect(z).toBeCloseTo(0); }); it("maps positive lateral input to the rendered camera's screen-right direction", () => { expect(cameraRelativeMovement(1, 0, 0)).toEqual([-1, 0]); expect(cameraRelativeMovement(-1, 0, 0)).toEqual([1, 0]); const yaw = 0.73; const [worldX, worldZ] = cameraRelativeMovement(1, 0, yaw); const screenRight = [-Math.cos(yaw), Math.sin(yaw)] as const; expect(worldX * screenRight[0] + worldZ * screenRight[1]).toBeCloseTo(1); }); it("turns toward screen-right for positive mouse or right-stick look", () => { expect(cameraYawAfterHorizontalLook(0, 0.25)).toBeCloseTo(-0.25); expect(cameraYawAfterHorizontalLook(0, -0.25)).toBeCloseTo(0.25); expect(cameraYawAfterHorizontalLook(0.7, Number.NaN)).toBeCloseTo(0.7); }); it("clamps pitch and wraps yaw", () => { expect(clampCameraPitch(-3)).toBe(-0.18); expect(clampCameraPitch(3)).toBe(0.88); expect(wrapAngle(Math.PI * 3)).toBeCloseTo(Math.PI); }); it("recovers from non-finite controller and camera values", () => { expect(applyRadialDeadzone(Number.NaN, 0)).toEqual([0, 0]); expect(normalizePlanar(Number.POSITIVE_INFINITY, 1)).toEqual([0, 0]); expect(cameraRelativeMovement(0, 1, Number.NaN)).toEqual([0, 1]); expect(cameraYawAfterHorizontalLook(Number.NaN, 1)).toBeCloseTo(-1); expect(clampCameraPitch(Number.NaN)).toBe(DEFAULT_CAMERA_PITCH); expect(wrapAngle(Number.NaN)).toBe(0); }); });