Add set project scheduler command and update scene document to include scheduler
This commit is contained in:
49
src/commands/set-project-scheduler-command.ts
Normal file
49
src/commands/set-project-scheduler-command.ts
Normal 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)
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user