Refactor project sequence handling and add whitebox brush geometry support

This commit is contained in:
2026-04-15 07:40:33 +02:00
parent d6c81008fe
commit bf662f76f2
8 changed files with 734 additions and 559 deletions

View File

@@ -98,7 +98,7 @@ describe("runtime project scheduler", () => {
expect.objectContaining({
actorId: "actor-night-watch",
hasRules: true,
active: false,
active: true,
activeRoutineId: null,
activeRoutineTitle: null
})
@@ -222,6 +222,59 @@ describe("runtime project scheduler", () => {
);
});
it("keeps actors visible outside active placements when they have sequence rules", () => {
const actorTarget = createActorControlTargetRef("actor-patrol");
const scheduler = createEmptyProjectScheduler();
const sequences = createEmptyProjectSequenceLibrary();
sequences.sequences["sequence-patrol"] = createProjectSequence({
id: "sequence-patrol",
title: "Patrol",
steps: [
{
stepClass: "held",
type: "controlEffect",
effect: createFollowActorPathControlEffect({
target: actorTarget,
pathId: "path-a",
speed: 1,
loop: false,
progressMode: "deriveFromTime"
})
}
]
});
scheduler.routines["routine-patrol"] = createProjectScheduleRoutine({
id: "routine-patrol",
title: "Patrol",
target: actorTarget,
startHour: 8,
endHour: 10,
sequenceId: "sequence-patrol",
effects: []
});
const resolved = resolveRuntimeProjectScheduleState({
scheduler,
sequences,
actorIds: ["actor-patrol"],
dayNumber: 1,
timeOfDayHours: 12
});
expect(resolved.actors[0]).toEqual(
expect.objectContaining({
actorId: "actor-patrol",
hasRules: true,
active: true,
activeRoutineId: null,
activeRoutineTitle: null,
resolvedPath: null
})
);
});
it("applies non-actor scheduler effects over baseline control state and restores defaults when inactive", () => {
const lightTarget = createLightControlTargetRef(
"pointLight",

View File

@@ -60,7 +60,7 @@ describe("ProjectSequencerPane", () => {
onSetRoutinePriority={vi.fn()}
onSetRoutineSequenceId={vi.fn()}
onSetSequenceTitle={vi.fn()}
onAddControlStep={vi.fn()}
onAddControlEffect={vi.fn()}
onAddDialogueStep={vi.fn()}
onAddTeleportStep={vi.fn()}
onAddSceneTransitionStep={vi.fn()}

View File

@@ -27,7 +27,7 @@ describe("ProjectSequencesPanel", () => {
]
});
const onAddControlStep = vi.fn();
const onAddControlEffect = vi.fn();
const onAddTeleportStep = vi.fn();
const onAddVisibilityStep = vi.fn();
const onSetTeleportStepTarget = vi.fn();
@@ -88,7 +88,7 @@ describe("ProjectSequencesPanel", () => {
onAddSequence={() => {}}
onDeleteSequence={() => {}}
onSetSequenceTitle={() => {}}
onAddControlStep={onAddControlStep}
onAddControlEffect={onAddControlEffect}
onAddDialogueStep={() => {}}
onAddTeleportStep={onAddTeleportStep}
onAddSceneTransitionStep={() => {}}
@@ -121,7 +121,9 @@ describe("ProjectSequencesPanel", () => {
target: { value: "hide" }
});
fireEvent.click(screen.getByRole("button", { name: "Add Effect" }));
fireEvent.click(
screen.getByRole("button", { name: "Add Model A Play Animation Effect" })
);
fireEvent.click(screen.getByRole("button", { name: "Add Teleport Effect" }));
fireEvent.click(screen.getByRole("button", { name: "Add Visibility Effect" }));
@@ -145,9 +147,10 @@ describe("ProjectSequencesPanel", () => {
"sequence-main",
"brush:brush-a"
);
expect(onAddControlStep).toHaveBeenCalledWith(
expect(onAddControlEffect).toHaveBeenCalledWith(
"sequence-main",
"modelInstance:model-a"
"modelInstance:model-a",
"model.playAnimation"
);
});
@@ -227,7 +230,7 @@ describe("ProjectSequencesPanel", () => {
onAddSequence={() => {}}
onDeleteSequence={() => {}}
onSetSequenceTitle={() => {}}
onAddControlStep={() => {}}
onAddControlEffect={() => {}}
onAddDialogueStep={() => {}}
onAddTeleportStep={() => {}}
onAddSceneTransitionStep={() => {}}