import type { GraphLookup } from '../graph/lookup'; import { startStateOf, statesOf, transitionsOf } from '../graph/stateMachine'; import { pictureSize } from '../properties/aspect'; import { resolveAssetProps } from '../properties/resolve'; import { clipOf } from './animation'; import { isGraphAsset, isVariableOwner } from './Asset'; import { bagWithoutItemTypes } from './Properties'; import { fieldTypings, typeFields, typingOf } from './structTypes'; import { findAsset, findAssetOf, type Project } from './Project'; import { resolvePicture } from './texture'; /** * What a graph may see of the project around it. A behavior's `defaults` are its variable values; * every call starts from a copy of them, except for the variables it keeps (#229). */ export function graphLookup(project: Project): GraphLookup { return { behavior: (assetId) => { const asset = findAssetOf(project, assetId, 'behavior'); if (!asset) return null; return { name: asset.name, graph: asset.graph, defaults: bagWithoutItemTypes(resolveAssetProps(project, asset)), kept: asset.keptVariables ?? [], }; }, machine: (assetId) => { const asset = findAssetOf(project, assetId, 'statemachine'); if (!asset) return null; return { name: asset.name, states: statesOf(asset.graph), transitions: transitionsOf(asset.graph), start: startStateOf(asset.graph, asset.start), }; }, curve: (assetId) => findAssetOf(project, assetId, 'curve')?.points ?? null, structType: (assetId) => { const asset = findAssetOf(project, assetId, 'struct'); if (!asset) return null; const fields = typeFields(asset); return { name: asset.name, fields: fields.map((f) => f.key), inner: fieldTypings(fields) ?? {} }; }, textureSize: (pictureId) => { const ref = resolvePicture(project, pictureId); return ref ? pictureSize(ref) : null; }, animation: (assetId) => { const asset = findAssetOf(project, assetId, 'animation'); return asset ? clipOf(asset) : null; }, collisionLayers: () => project.collisionLayers, ownerOf: (graph) => project.assets.find((a) => isGraphAsset(a) && a.graph === graph)?.id ?? '', variableTyping: (assetId, key) => { const owner = findAsset(project, assetId); const def = owner && isVariableOwner(owner) ? owner.variables.find((v) => v.key === key) : undefined; return def && typingOf(def); }, }; }