Add buildTree to mirror how TTS nests objects, with a display label (Nickname or class Name). Generalize traverseMod to descend into any object with ContainedObjects, not just bags, and add Nickname to TTSObject.
59 lines
1.5 KiB
TypeScript
59 lines
1.5 KiB
TypeScript
import type { TTSMod, TTSObject } from '@tts/shared';
|
|
import { markParent, traverseMod } from './traverse.js';
|
|
|
|
/** A node in the containment tree of a save. */
|
|
export interface ObjectTreeNode {
|
|
object: TTSObject;
|
|
/** Display label: `Nickname` when present, else the class `Name`. */
|
|
label: string;
|
|
children: ObjectTreeNode[];
|
|
}
|
|
|
|
/**
|
|
* Build the containment tree of a save, mirroring how TTS nests objects.
|
|
* Each node carries its object plus a display label and its children.
|
|
*/
|
|
export function buildTree(mod: TTSMod): ObjectTreeNode[] {
|
|
for (const state of mod.ObjectStates) {
|
|
markParent(state);
|
|
}
|
|
return mod.ObjectStates.map(nodeFrom);
|
|
}
|
|
|
|
function nodeFrom(o: TTSObject): ObjectTreeNode {
|
|
return {
|
|
object: o,
|
|
label: o.Nickname || o.Name,
|
|
children: (o.ContainedObjects ?? []).map(nodeFrom),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Flatten all objects in a save into an array.
|
|
* Ensures parent links are set before returning.
|
|
*/
|
|
export function flattenObjects(mod: TTSMod): TTSObject[] {
|
|
for (const state of mod.ObjectStates) {
|
|
markParent(state);
|
|
}
|
|
return [...traverseMod(mod)];
|
|
}
|
|
|
|
/**
|
|
* Filter objects by a predicate (name, GUID, type, etc.).
|
|
*/
|
|
export function filterObjects(
|
|
mod: TTSMod,
|
|
predicate: (o: TTSObject) => boolean,
|
|
): TTSObject[] {
|
|
return flattenObjects(mod).filter(predicate);
|
|
}
|
|
|
|
/**
|
|
* Find a single object by GUID.
|
|
*/
|
|
export function findObject(mod: TTSMod, guid: string): TTSObject | undefined {
|
|
return flattenObjects(mod).find((o) => o.GUID === guid);
|
|
}
|
|
|
|
export { markParent, traverseMod } from './traverse.js'; |