Add set project scheduler command and update scene document to include scheduler

This commit is contained in:
2026-04-14 01:53:02 +02:00
parent 05d513464e
commit 5facb6f136
3 changed files with 124 additions and 3 deletions

View File

@@ -0,0 +1,49 @@
import { createOpaqueId } from "../core/ids";
import {
cloneProjectScheduler,
type ProjectScheduler
} from "../scheduler/project-scheduler";
import type { EditorCommand } from "./command";
interface SetProjectSchedulerCommandOptions {
label: string;
scheduler: ProjectScheduler;
}
export function createSetProjectSchedulerCommand(
options: SetProjectSchedulerCommandOptions
): EditorCommand {
const nextScheduler = cloneProjectScheduler(options.scheduler);
let previousScheduler: ProjectScheduler | null = null;
return {
id: createOpaqueId("command"),
label: options.label,
execute(context) {
const currentProjectDocument = context.getProjectDocument();
if (previousScheduler === null) {
previousScheduler = cloneProjectScheduler(
currentProjectDocument.scheduler
);
}
context.setProjectDocument({
...currentProjectDocument,
scheduler: cloneProjectScheduler(nextScheduler)
});
},
undo(context) {
if (previousScheduler === null) {
return;
}
const currentProjectDocument = context.getProjectDocument();
context.setProjectDocument({
...currentProjectDocument,
scheduler: cloneProjectScheduler(previousScheduler)
});
}
};
}

View File

@@ -19,8 +19,13 @@ import {
type ProjectTimeSettings
} from "./project-time-settings";
import { type ScenePath } from "./paths";
import {
createEmptyProjectScheduler,
type ProjectScheduler
} from "../scheduler/project-scheduler";
export const SCENE_DOCUMENT_VERSION = 45 as const;
export const SCENE_DOCUMENT_VERSION = 46 as const;
export const PROJECT_SCHEDULER_FOUNDATION_SCENE_DOCUMENT_VERSION = 46 as const;
export const CONTROL_SURFACE_FOUNDATION_SCENE_DOCUMENT_VERSION = 45 as const;
export const NPC_PRESENCE_SCENE_DOCUMENT_VERSION = 44 as const;
export const PATH_FOUNDATION_SCENE_DOCUMENT_VERSION = 43 as const;
@@ -136,6 +141,7 @@ export interface ProjectDocument {
version: typeof SCENE_DOCUMENT_VERSION;
name: string;
time: ProjectTimeSettings;
scheduler: ProjectScheduler;
activeSceneId: string;
scenes: Record<string, ProjectScene>;
materials: Record<string, MaterialDef>;
@@ -147,6 +153,7 @@ export interface SceneDocument {
version: typeof SCENE_DOCUMENT_VERSION;
name: string;
time: ProjectTimeSettings;
scheduler: ProjectScheduler;
world: WorldSettings;
materials: Record<string, MaterialDef>;
textures: Record<string, never>;
@@ -167,6 +174,7 @@ export function createEmptySceneDocument(
version: SCENE_DOCUMENT_VERSION,
name: overrides.name ?? "Untitled Scene",
time: overrides.time ?? createDefaultProjectTimeSettings(),
scheduler: createEmptyProjectScheduler(),
world: overrides.world ?? createDefaultWorldSettings(),
materials: cloneMaterialRegistry(
overrides.materials ?? createStarterMaterialRegistry()
@@ -211,7 +219,13 @@ export function createEmptyProjectDocument(
overrides: Partial<
Pick<
ProjectDocument,
"name" | "time" | "activeSceneId" | "materials" | "textures" | "assets"
| "name"
| "time"
| "scheduler"
| "activeSceneId"
| "materials"
| "textures"
| "assets"
>
> & {
sceneId?: string;
@@ -230,6 +244,7 @@ export function createEmptyProjectDocument(
version: SCENE_DOCUMENT_VERSION,
name: overrides.name ?? DEFAULT_PROJECT_NAME,
time: overrides.time ?? createDefaultProjectTimeSettings(),
scheduler: overrides.scheduler ?? createEmptyProjectScheduler(),
activeSceneId: initialScene.id,
scenes: {
[initialScene.id]: initialScene
@@ -265,6 +280,7 @@ export function createSceneDocumentFromProject(
version: projectDocument.version,
name: scene.name,
time: projectDocument.time,
scheduler: projectDocument.scheduler,
world: scene.world,
materials: projectDocument.materials,
textures: projectDocument.textures,
@@ -286,6 +302,7 @@ export function createProjectDocumentFromSceneDocument(
version: SCENE_DOCUMENT_VERSION,
name: projectName,
time: sceneDocument.time,
scheduler: sceneDocument.scheduler,
activeSceneId: sceneId,
scenes: {
[sceneId]: {
@@ -318,6 +335,7 @@ export function applySceneDocumentToProject(
...projectDocument,
version: SCENE_DOCUMENT_VERSION,
time: sceneDocument.time,
scheduler: sceneDocument.scheduler,
materials: sceneDocument.materials,
textures: sceneDocument.textures,
assets: sceneDocument.assets,

View File

@@ -10,6 +10,12 @@ export interface NpcActorUsage {
entityName?: string;
}
export interface ProjectNpcActorRecord {
actorId: string;
label: string;
usages: NpcActorUsage[];
}
export function listNpcActorUsages(
projectDocument: ProjectDocument,
actorId: string
@@ -48,4 +54,52 @@ export function listNpcActorUsages(
});
return usages;
}
}
export function listProjectNpcActors(
projectDocument: ProjectDocument
): ProjectNpcActorRecord[] {
const actorUsages = new Map<string, NpcActorUsage[]>();
for (const scene of Object.values(projectDocument.scenes)) {
for (const entity of getEntityInstances(scene.entities)) {
if (entity.kind !== "npc") {
continue;
}
const usages = actorUsages.get(entity.actorId) ?? [];
usages.push({
actorId: entity.actorId,
sceneId: scene.id,
sceneName: scene.name,
entityId: entity.id,
entityName: entity.name
});
actorUsages.set(entity.actorId, usages);
}
}
return [...actorUsages.entries()]
.map(([actorId, usages]) => {
usages.sort((left, right) => {
return (
left.sceneName.localeCompare(right.sceneName) ||
left.sceneId.localeCompare(right.sceneId) ||
(left.entityName ?? "").localeCompare(right.entityName ?? "") ||
left.entityId.localeCompare(right.entityId)
);
});
return {
actorId,
label: usages[0]?.entityName?.trim() || actorId,
usages
};
})
.sort((left, right) => {
return (
left.label.localeCompare(right.label) ||
left.actorId.localeCompare(right.actorId)
);
});
}