feat: edit moving source trajectories
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
import { coordinateToPixel, pixelToCoordinate } from "/apps/dataset-builder/canvas-view.js";
|
||||
import {
|
||||
assetDescriptorForFile,
|
||||
disableSourceTrajectory,
|
||||
enableSourceTrajectory,
|
||||
createSceneId,
|
||||
createSource,
|
||||
insertTrajectoryKeyframe,
|
||||
matchAssetDescriptor,
|
||||
prepareSceneForEditing,
|
||||
removeTrajectoryKeyframe,
|
||||
referencedAssetIds,
|
||||
scaleSceneTrajectories,
|
||||
updateTrajectoryKeyframeTime,
|
||||
} from "/apps/dataset-builder/model.js";
|
||||
import { decodeAudioFile } from "/packages/audio-io/browser-audio.js";
|
||||
import {
|
||||
@@ -43,6 +49,31 @@ test("Builder model이 schema-safe하고 안정적인 source/asset id를 만든
|
||||
assert(/^[a-z0-9][a-z0-9._-]*$/.test(createSceneId()), "generated scene id is schema-safe");
|
||||
});
|
||||
|
||||
test("Builder가 이동 경로를 순서대로 편집하고 fallback position을 첫 점에 맞춘다", () => {
|
||||
const source = { position: [0.5, 0.1, 2] };
|
||||
const trajectory = enableSourceTrajectory(source, 2, { xMin: -0.6, xMax: 0.6, yMin: -0.45, yMax: 0.45 });
|
||||
assertEqual(trajectory.length, 2, "default keyframe count");
|
||||
assertEqual(trajectory[0].time, 0, "path starts at scene start");
|
||||
assertEqual(trajectory[1].time, 2, "path spans scene duration");
|
||||
assert(trajectory[1].position[0] < trajectory[0].position[0], "edge path turns inward");
|
||||
|
||||
const inserted = insertTrajectoryKeyframe(source);
|
||||
assertEqual(inserted, 1, "midpoint insertion index");
|
||||
assertNear(source.trajectory[1].time, 1, 1e-12, "midpoint time");
|
||||
assertNear(source.trajectory[1].position[0], 0.35, 1e-12, "midpoint x");
|
||||
assertNear(updateTrajectoryKeyframeTime(source, 1, 3, 2), 1.999999998, 1e-12, "ordered time clamp");
|
||||
|
||||
source.trajectory[0].position = [-0.25, 0.2, 1.5];
|
||||
scaleSceneTrajectories({ sources: [source] }, 2, 4);
|
||||
assertNear(source.trajectory[1].time, 3.999999996, 1e-9, "duration scales keyframes");
|
||||
assertEqual(source.position.join(","), "-0.25,0.2,1.5", "first point fallback sync");
|
||||
assert(removeTrajectoryKeyframe(source, 1), "remove optional midpoint");
|
||||
assertEqual(removeTrajectoryKeyframe(source, 0), false, "two-point minimum");
|
||||
disableSourceTrajectory(source);
|
||||
assertEqual(source.trajectory, undefined, "motion disabled");
|
||||
assertEqual(source.position.join(","), "-0.25,0.2,1.5", "fallback remains after disable");
|
||||
});
|
||||
|
||||
test("asset 재연결은 fileName보다 SHA-256을 우선하고 충돌을 분리한다", () => {
|
||||
const assets = [
|
||||
{ id: "old", kind: "audio", fileName: "audio/machine.wav", sha256: "a".repeat(64) },
|
||||
|
||||
Reference in New Issue
Block a user