import { Group, Scene } from "three"; import { beforeEach, describe, expect, it } from "vitest"; import type { DirectorObject } from "../schema/directorProject"; import { createDefaultDirectorProject, useDirectorStore } from "../store/directorStore"; import { getViewportCaptureLabels } from "./DirectorCanvas"; describe("getViewportCaptureLabels", () => { beforeEach(() => { useDirectorStore.getState().replaceProject(createDefaultDirectorProject()); }); it("places each label at the character's real scene position, not its static transform (0,0,0)", () => { const project = createDefaultDirectorProject(); const characters = project.objects.filter((o): o is DirectorObject => o.kind === "character"); expect(characters.length).toBeGreaterThan(0); // 把所有角色静态 transform 摆到原点,但在场景里把它们挪到别处 —— // 截图标签必须贴着「场景里真实的位置」,而不是落回 0 点坐标。 const scene = new Scene(); const nameToPosition = new Map(); characters.forEach((item, index) => { const group = new Group(); group.userData.directorObjectId = item.id; const position: [number, number, number] = [10 + index, 0.5, 20 + index]; group.position.set(position[0], position[1], position[2]); scene.add(group); nameToPosition.set(item.name, position); item.transform.position = [0, 0, 0]; }); useDirectorStore.getState().replaceProject(project); const labels = getViewportCaptureLabels(scene); expect(labels.length).toBe(characters.length); for (const label of labels) { const expected = nameToPosition.get(label.text); expect(expected).toBeTruthy(); // 用 x / z 验证:若误用静态 transform(原点),这里会是 0 expect(label.worldPosition.x).toBeCloseTo(expected![0], 5); expect(label.worldPosition.z).toBeCloseTo(expected![2], 5); // y 在角色头部高度(基础 y + 标签高度),应高于场景里摆放的 y expect(label.worldPosition.y).toBeGreaterThan(expected![1]); } }); it("returns nothing when scene.showLabels is off", () => { const project = createDefaultDirectorProject(); project.scene.showLabels = false; useDirectorStore.getState().replaceProject(project); expect(getViewportCaptureLabels(new Scene())).toEqual([]); }); }); describe("captureShowGrid setting", () => { beforeEach(() => { useDirectorStore.getState().replaceProject(createDefaultDirectorProject()); }); it("defaults to false (grid hidden during capture) and toggles", () => { expect(useDirectorStore.getState().project.scene.captureShowGrid).toBe(false); useDirectorStore.getState().updateScene({ captureShowGrid: true }); expect(useDirectorStore.getState().project.scene.captureShowGrid).toBe(true); }); });