feat(extract): build containment tree and traverse all containers

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.
This commit is contained in:
2026-08-08 12:19:39 +08:00
parent e2d87df1a4
commit d8a698986a
5 changed files with 75 additions and 12 deletions
+27
View File
@@ -1,6 +1,33 @@
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.