Files
webeditor3d/src/dialogues/project-dialogues.ts

137 lines
3.1 KiB
TypeScript

import { createOpaqueId } from "../core/ids";
export interface ProjectDialogueLine {
id: string;
text: string;
}
export interface ProjectDialogue {
id: string;
title: string;
lines: ProjectDialogueLine[];
}
export interface ProjectDialogueLibrary {
dialogues: Record<string, ProjectDialogue>;
}
export function createEmptyProjectDialogueLibrary(): ProjectDialogueLibrary {
return {
dialogues: {}
};
}
export function createProjectDialogueLine(
overrides: Partial<ProjectDialogueLine> = {}
): ProjectDialogueLine {
return {
id: overrides.id ?? createOpaqueId("dialogue-line"),
text: overrides.text ?? "..."
};
}
export function createProjectDialogue(
overrides: Partial<Pick<ProjectDialogue, "id" | "title">> & {
lines?: ProjectDialogueLine[];
} = {}
): ProjectDialogue {
return {
id: overrides.id ?? createOpaqueId("dialogue"),
title: overrides.title?.trim() || "Untitled Dialogue",
lines:
overrides.lines?.map(cloneProjectDialogueLine) ?? [
createProjectDialogueLine()
]
};
}
export function cloneProjectDialogueLine(
line: ProjectDialogueLine
): ProjectDialogueLine {
return {
id: line.id,
text: line.text
};
}
export function cloneProjectDialogue(
dialogue: ProjectDialogue
): ProjectDialogue {
return {
id: dialogue.id,
title: dialogue.title,
lines: dialogue.lines.map(cloneProjectDialogueLine)
};
}
export function cloneProjectDialogueLibrary(
library: ProjectDialogueLibrary
): ProjectDialogueLibrary {
return {
dialogues: Object.fromEntries(
Object.entries(library.dialogues).map(([dialogueId, dialogue]) => [
dialogueId,
cloneProjectDialogue(dialogue)
])
)
};
}
export function areProjectDialogueLinesEqual(
left: ProjectDialogueLine,
right: ProjectDialogueLine
): boolean {
return left.id === right.id && left.text === right.text;
}
export function areProjectDialoguesEqual(
left: ProjectDialogue,
right: ProjectDialogue
): boolean {
if (
left.id !== right.id ||
left.title !== right.title ||
left.lines.length !== right.lines.length
) {
return false;
}
return left.lines.every((line, index) =>
areProjectDialogueLinesEqual(line, right.lines[index]!)
);
}
export function areProjectDialogueLibrariesEqual(
left: ProjectDialogueLibrary,
right: ProjectDialogueLibrary
): boolean {
const leftIds = Object.keys(left.dialogues);
const rightIds = Object.keys(right.dialogues);
if (leftIds.length !== rightIds.length) {
return false;
}
return leftIds.every((dialogueId) => {
const rightDialogue = right.dialogues[dialogueId];
return (
rightDialogue !== undefined &&
areProjectDialoguesEqual(left.dialogues[dialogueId]!, rightDialogue)
);
});
}
export function getProjectDialogues(
library: ProjectDialogueLibrary
): ProjectDialogue[] {
return Object.values(library.dialogues).sort((left, right) => {
const titleCompare = left.title.localeCompare(right.title);
if (titleCompare !== 0) {
return titleCompare;
}
return left.id.localeCompare(right.id);
});
}