Add scene creation and active scene switching commands
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
import type { EditorSelection } from "../core/selection";
|
||||
import type { ToolMode } from "../core/tool-mode";
|
||||
import type { SceneDocument } from "../document/scene-document";
|
||||
import type { ProjectDocument, SceneDocument } from "../document/scene-document";
|
||||
|
||||
export interface CommandContext {
|
||||
getDocument(): SceneDocument;
|
||||
setDocument(document: SceneDocument): void;
|
||||
getProjectDocument(): ProjectDocument;
|
||||
setProjectDocument(document: ProjectDocument): void;
|
||||
getSelection(): EditorSelection;
|
||||
setSelection(selection: EditorSelection): void;
|
||||
getToolMode(): ToolMode;
|
||||
|
||||
68
src/commands/create-scene-command.ts
Normal file
68
src/commands/create-scene-command.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { createOpaqueId } from "../core/ids";
|
||||
import { createEmptyProjectScene } from "../document/scene-document";
|
||||
|
||||
import type { EditorCommand } from "./command";
|
||||
|
||||
function createUniqueSceneName(existingNames: string[]): string {
|
||||
const normalizedNames = new Set(
|
||||
existingNames.map((name) => name.trim().toLowerCase())
|
||||
);
|
||||
let suffix = existingNames.length + 1;
|
||||
|
||||
while (normalizedNames.has(`scene ${suffix}`)) {
|
||||
suffix += 1;
|
||||
}
|
||||
|
||||
return `Scene ${suffix}`;
|
||||
}
|
||||
|
||||
export function createCreateSceneCommand(): EditorCommand {
|
||||
const createdSceneId = createOpaqueId("scene");
|
||||
let createdSceneName: string | null = null;
|
||||
let previousProjectDocumentSerialized: string | null = null;
|
||||
|
||||
return {
|
||||
id: createOpaqueId("command"),
|
||||
label: "Create scene",
|
||||
execute(context) {
|
||||
const currentProjectDocument = context.getProjectDocument();
|
||||
|
||||
if (previousProjectDocumentSerialized === null) {
|
||||
previousProjectDocumentSerialized = JSON.stringify(currentProjectDocument);
|
||||
}
|
||||
|
||||
if (createdSceneName === null) {
|
||||
createdSceneName = createUniqueSceneName(
|
||||
Object.values(currentProjectDocument.scenes).map((scene) => scene.name)
|
||||
);
|
||||
}
|
||||
|
||||
context.setProjectDocument({
|
||||
...currentProjectDocument,
|
||||
activeSceneId: createdSceneId,
|
||||
scenes: {
|
||||
...currentProjectDocument.scenes,
|
||||
[createdSceneId]: createEmptyProjectScene({
|
||||
id: createdSceneId,
|
||||
name: createdSceneName
|
||||
})
|
||||
}
|
||||
});
|
||||
context.setSelection({ kind: "none" });
|
||||
context.setToolMode("select");
|
||||
},
|
||||
undo(context) {
|
||||
if (previousProjectDocumentSerialized === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
context.setProjectDocument(
|
||||
JSON.parse(previousProjectDocumentSerialized) as ReturnType<
|
||||
typeof context.getProjectDocument
|
||||
>
|
||||
);
|
||||
context.setSelection({ kind: "none" });
|
||||
context.setToolMode("select");
|
||||
}
|
||||
};
|
||||
}
|
||||
48
src/commands/set-active-scene-command.ts
Normal file
48
src/commands/set-active-scene-command.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { createOpaqueId } from "../core/ids";
|
||||
|
||||
import type { EditorCommand } from "./command";
|
||||
|
||||
export function createSetActiveSceneCommand(nextSceneId: string): EditorCommand {
|
||||
let previousSceneId: string | null = null;
|
||||
|
||||
return {
|
||||
id: createOpaqueId("command"),
|
||||
label: "Switch active scene",
|
||||
execute(context) {
|
||||
const currentProjectDocument = context.getProjectDocument();
|
||||
|
||||
if (currentProjectDocument.scenes[nextSceneId] === undefined) {
|
||||
throw new Error(`Cannot activate missing scene ${nextSceneId}.`);
|
||||
}
|
||||
|
||||
if (previousSceneId === null) {
|
||||
previousSceneId = currentProjectDocument.activeSceneId;
|
||||
}
|
||||
|
||||
context.setProjectDocument({
|
||||
...currentProjectDocument,
|
||||
activeSceneId: nextSceneId
|
||||
});
|
||||
context.setSelection({ kind: "none" });
|
||||
context.setToolMode("select");
|
||||
},
|
||||
undo(context) {
|
||||
if (previousSceneId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentProjectDocument = context.getProjectDocument();
|
||||
|
||||
if (currentProjectDocument.scenes[previousSceneId] === undefined) {
|
||||
throw new Error(`Cannot restore missing scene ${previousSceneId}.`);
|
||||
}
|
||||
|
||||
context.setProjectDocument({
|
||||
...currentProjectDocument,
|
||||
activeSceneId: previousSceneId
|
||||
});
|
||||
context.setSelection({ kind: "none" });
|
||||
context.setToolMode("select");
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user