From 3a81027203695f73522c91ff37bf9ca4d090abcd Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Sat, 25 Apr 2026 03:07:04 +0200 Subject: [PATCH] auto-git: [add] tests/unit/dialogue-attention-camera.test.ts --- tests/unit/dialogue-attention-camera.test.ts | 116 +++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 tests/unit/dialogue-attention-camera.test.ts diff --git a/tests/unit/dialogue-attention-camera.test.ts b/tests/unit/dialogue-attention-camera.test.ts new file mode 100644 index 00000000..89f4fc55 --- /dev/null +++ b/tests/unit/dialogue-attention-camera.test.ts @@ -0,0 +1,116 @@ +import { describe, expect, it } from "vitest"; + +import { resolveDialogueAttentionCameraSolution } from "../../src/runtime-three/dialogue-attention-camera"; + +describe("resolveDialogueAttentionCameraSolution", () => { + it("chooses a stable shoulder side from the reference camera and biases framing toward the NPC", () => { + const solution = resolveDialogueAttentionCameraSolution({ + playerFocusPoint: { + x: 0, + y: 1.6, + z: 0 + }, + npcFocusPoint: { + x: 2, + y: 1.7, + z: 2 + }, + referenceCameraPosition: { + x: 4, + y: 2.2, + z: -2 + }, + referenceLookTarget: { + x: 1, + y: 1.65, + z: 1 + } + }); + + expect(solution.sideSign).toBe(1); + expect(solution.position.y).toBeGreaterThan(2); + expect(solution.lookTarget.x).toBeGreaterThan(1); + expect(solution.lookTarget.z).toBeGreaterThan(1); + }); + + it("preserves the authored dialogue side sign across solver updates", () => { + const solution = resolveDialogueAttentionCameraSolution({ + playerFocusPoint: { + x: 0, + y: 1.6, + z: 0 + }, + npcFocusPoint: { + x: 2, + y: 1.7, + z: 2 + }, + referenceCameraPosition: { + x: -4, + y: 2.2, + z: 4 + }, + referenceLookTarget: { + x: 1, + y: 1.65, + z: 1 + }, + previousSideSign: 1 + }); + + expect(solution.sideSign).toBe(1); + }); + + it("backs the camera away as the conversation span grows", () => { + const narrow = resolveDialogueAttentionCameraSolution({ + playerFocusPoint: { + x: 0, + y: 1.6, + z: 0 + }, + npcFocusPoint: { + x: 1.5, + y: 1.6, + z: 1.5 + }, + referenceCameraPosition: { + x: 3, + y: 2.2, + z: -2 + }, + referenceLookTarget: { + x: 0.75, + y: 1.6, + z: 0.75 + } + }); + const wide = resolveDialogueAttentionCameraSolution({ + playerFocusPoint: { + x: 0, + y: 1.6, + z: 0 + }, + npcFocusPoint: { + x: 4, + y: 1.6, + z: 4 + }, + referenceCameraPosition: { + x: 3, + y: 2.2, + z: -2 + }, + referenceLookTarget: { + x: 2, + y: 1.6, + z: 2 + } + }); + + expect(wide.subjectDistance).toBeGreaterThan(narrow.subjectDistance); + expect(wide.position.y).toBeGreaterThanOrEqual(narrow.position.y); + expect(Math.hypot(wide.position.x, wide.position.z)).toBeGreaterThan( + Math.hypot(narrow.position.x, narrow.position.z) + ); + }); +});