@babylonjs/loaders 9.26.0 → 9.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/FBX/fbxConstraintBehavior.d.ts +188 -0
  2. package/FBX/fbxConstraintBehavior.js +532 -0
  3. package/FBX/fbxConstraintBehavior.js.map +1 -0
  4. package/FBX/fbxFileLoader.pure.d.ts +175 -6
  5. package/FBX/fbxFileLoader.pure.js +1521 -286
  6. package/FBX/fbxFileLoader.pure.js.map +1 -1
  7. package/FBX/index.d.ts +4 -1
  8. package/FBX/index.js +1 -0
  9. package/FBX/index.js.map +1 -1
  10. package/FBX/interpreter/animation.d.ts +73 -33
  11. package/FBX/interpreter/animation.js +620 -223
  12. package/FBX/interpreter/animation.js.map +1 -1
  13. package/FBX/interpreter/animationCurve.d.ts +91 -0
  14. package/FBX/interpreter/animationCurve.js +623 -0
  15. package/FBX/interpreter/animationCurve.js.map +1 -0
  16. package/FBX/interpreter/blendShapes.js +9 -18
  17. package/FBX/interpreter/blendShapes.js.map +1 -1
  18. package/FBX/interpreter/connections.d.ts +1 -1
  19. package/FBX/interpreter/connections.js +173 -34
  20. package/FBX/interpreter/connections.js.map +1 -1
  21. package/FBX/interpreter/constraints.d.ts +68 -0
  22. package/FBX/interpreter/constraints.js +143 -0
  23. package/FBX/interpreter/constraints.js.map +1 -0
  24. package/FBX/interpreter/fbxInterpreter.d.ts +89 -4
  25. package/FBX/interpreter/fbxInterpreter.js +474 -122
  26. package/FBX/interpreter/fbxInterpreter.js.map +1 -1
  27. package/FBX/interpreter/geometry.d.ts +1 -1
  28. package/FBX/interpreter/geometry.js +150 -92
  29. package/FBX/interpreter/geometry.js.map +1 -1
  30. package/FBX/interpreter/legacyDocument.d.ts +11 -0
  31. package/FBX/interpreter/legacyDocument.js +425 -0
  32. package/FBX/interpreter/legacyDocument.js.map +1 -0
  33. package/FBX/interpreter/materialModel.d.ts +71 -0
  34. package/FBX/interpreter/materialModel.js +622 -0
  35. package/FBX/interpreter/materialModel.js.map +1 -0
  36. package/FBX/interpreter/materials.d.ts +13 -1
  37. package/FBX/interpreter/materials.js +88 -5
  38. package/FBX/interpreter/materials.js.map +1 -1
  39. package/FBX/interpreter/nodeTransform.d.ts +32 -0
  40. package/FBX/interpreter/nodeTransform.js +54 -0
  41. package/FBX/interpreter/nodeTransform.js.map +1 -0
  42. package/FBX/interpreter/nurbs.d.ts +99 -0
  43. package/FBX/interpreter/nurbs.js +627 -0
  44. package/FBX/interpreter/nurbs.js.map +1 -0
  45. package/FBX/interpreter/propertyTemplates.d.ts +23 -0
  46. package/FBX/interpreter/propertyTemplates.js +109 -2
  47. package/FBX/interpreter/propertyTemplates.js.map +1 -1
  48. package/FBX/interpreter/rig.js +16 -0
  49. package/FBX/interpreter/rig.js.map +1 -1
  50. package/FBX/interpreter/sceneDiagnostics.js +28 -3
  51. package/FBX/interpreter/sceneDiagnostics.js.map +1 -1
  52. package/FBX/interpreter/skeleton.d.ts +4 -18
  53. package/FBX/interpreter/skeleton.js +16 -94
  54. package/FBX/interpreter/skeleton.js.map +1 -1
  55. package/FBX/parsers/fbxAsciiParser.js +119 -9
  56. package/FBX/parsers/fbxAsciiParser.js.map +1 -1
  57. package/FBX/parsers/fbxBinaryParser.js +74 -22
  58. package/FBX/parsers/fbxBinaryParser.js.map +1 -1
  59. package/FBX/pure.d.ts +1 -0
  60. package/FBX/pure.js +1 -0
  61. package/FBX/pure.js.map +1 -1
  62. package/FBX/types/fbxTypes.d.ts +18 -2
  63. package/FBX/types/fbxTypes.js +40 -12
  64. package/FBX/types/fbxTypes.js.map +1 -1
  65. package/USD/usdCommandProtocol.d.ts +20 -4
  66. package/USD/usdCommandProtocol.js +25 -3
  67. package/USD/usdCommandProtocol.js.map +1 -1
  68. package/USD/usdFileLoader.pure.js +2 -0
  69. package/USD/usdFileLoader.pure.js.map +1 -1
  70. package/USD/usdSceneMaterializer.js +430 -92
  71. package/USD/usdSceneMaterializer.js.map +1 -1
  72. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"connections.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/interpreter/connections.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\r\nimport { type FBXDocument, type FBXNode, cleanFBXName, findDocumentNode, getPropertyValue, getSafeFBXObjectId } from \"../types/fbxTypes\";\r\n\r\n/** Connection type: OO = object-to-object, OP = object-to-property */\r\nexport type ConnectionType = \"OO\" | \"OP\";\r\n\r\n/** A resolved FBX object connection. */\r\nexport interface FBXConnection {\r\n /** Connection type. */\r\n type: ConnectionType;\r\n /** Child object ID. */\r\n childId: number;\r\n /** Parent object ID. */\r\n parentId: number;\r\n /** For OP connections, the property name on the parent (e.g. \"DiffuseColor\") */\r\n propertyName?: string;\r\n}\r\n\r\n/** Object table entry used by the FBX connection graph. */\r\nexport interface FBXObjectEntry {\r\n /** Object ID. */\r\n id: number;\r\n /** Object node. */\r\n node: FBXNode;\r\n /** Source of the object entry. */\r\n source: \"Objects\" | \"legacySyntheticGeometry\";\r\n /** Legacy string object name, when applicable. */\r\n legacyName?: string;\r\n /** True if the object was synthesized for legacy compatibility. */\r\n synthetic: boolean;\r\n}\r\n\r\n/** Raw connection-table entry and import status. */\r\nexport interface FBXConnectionEntry {\r\n /** Source node name. */\r\n source: \"C\" | \"Connect\";\r\n /** Raw connection type. */\r\n rawType?: string;\r\n /** Child object ID, when resolved. */\r\n childId?: number;\r\n /** Parent object ID, when resolved. */\r\n parentId?: number;\r\n /** OP connection property name, when present. */\r\n propertyName?: string;\r\n /** True if the connection was accepted into the resolved graph. */\r\n accepted: boolean;\r\n}\r\n\r\n/** Reason a connection produced a diagnostic. */\r\nexport type FBXConnectionDiagnosticReason =\r\n \"unsupported-connection-type\" | \"missing-connection-endpoint\" | \"unresolved-legacy-endpoint\" | \"unresolved-object-reference\" | \"duplicate-parent\" | \"self-loop\";\r\n\r\n/** Recoverable connection graph issue. */\r\nexport interface FBXConnectionDiagnostic {\r\n /** Diagnostic reason. */\r\n reason: FBXConnectionDiagnosticReason;\r\n /** Human-readable diagnostic message. */\r\n message: string;\r\n /** Connection-table index associated with the diagnostic, if applicable. */\r\n connectionIndex?: number;\r\n /** Connection type associated with the diagnostic, if applicable. */\r\n type?: string;\r\n /** Child object ID associated with the diagnostic, if applicable. */\r\n childId?: number;\r\n /** Parent object ID associated with the diagnostic, if applicable. */\r\n parentId?: number;\r\n /** OP connection property name associated with the diagnostic, if applicable. */\r\n propertyName?: string;\r\n}\r\n\r\n/** Resolved FBX object and connection graph. */\r\nexport interface FBXObjectMap {\r\n /** All objects by their unique ID */\r\n objects: Map<number, FBXNode>;\r\n /** Object table entries, including synthetic compatibility objects */\r\n objectEntries: FBXObjectEntry[];\r\n /** Children of each object ID */\r\n childrenOf: Map<number, { id: number; propertyName?: string }[]>;\r\n /** Parent of each object ID */\r\n parentOf: Map<number, { id: number; propertyName?: string }>;\r\n /** Raw connection list */\r\n connections: FBXConnection[];\r\n /** Raw connection-table entries and whether they were accepted into the graph */\r\n connectionEntries: FBXConnectionEntry[];\r\n /** Unsupported or suspicious connection shapes encountered while preserving graph behavior */\r\n diagnostics: FBXConnectionDiagnostic[];\r\n}\r\n\r\n/**\r\n * Build a connection graph from a parsed FBX document.\r\n * Maps object IDs to their FBXNode and resolves parent-child relationships.\r\n */\r\nexport function resolveConnections(doc: FBXDocument): FBXObjectMap {\r\n const objects = new Map<number, FBXNode>();\r\n const objectEntries: FBXObjectEntry[] = [];\r\n const childrenOf = new Map<number, { id: number; propertyName?: string }[]>();\r\n const parentOf = new Map<number, { id: number; propertyName?: string }>();\r\n const connections: FBXConnection[] = [];\r\n const connectionEntries: FBXConnectionEntry[] = [];\r\n const diagnostics: FBXConnectionDiagnostic[] = [];\r\n const legacyIds = new Map<string, number>();\r\n const syntheticLegacyIds = new Map<string, Map<string, number>>();\r\n let nextLegacyId = -1;\r\n\r\n const getLegacyId = (name: string): number => {\r\n let id = legacyIds.get(name);\r\n if (id === undefined) {\r\n id = nextLegacyId--;\r\n legacyIds.set(name, id);\r\n }\r\n return id;\r\n };\r\n\r\n const getSyntheticLegacyId = (role: string, name: string): number => {\r\n let idsByName = syntheticLegacyIds.get(role);\r\n if (!idsByName) {\r\n idsByName = new Map();\r\n syntheticLegacyIds.set(role, idsByName);\r\n }\r\n\r\n let id = idsByName.get(name);\r\n if (id === undefined) {\r\n id = nextLegacyId--;\r\n idsByName.set(name, id);\r\n }\r\n return id;\r\n };\r\n\r\n // Build object map from Objects section\r\n const objectsNode = findDocumentNode(doc, \"Objects\");\r\n if (objectsNode) {\r\n for (const obj of objectsNode.children) {\r\n const idProp = obj.properties[0];\r\n if (idProp) {\r\n const id = toObjectNumber(idProp.value);\r\n if (id !== undefined) {\r\n objects.set(id, obj);\r\n objectEntries.push({ id, node: obj, source: \"Objects\", synthetic: false });\r\n } else if (typeof idProp.value === \"string\") {\r\n const legacyName = cleanFBXName(idProp.value);\r\n const id = getLegacyId(legacyName);\r\n const normalized = normalizeLegacyObject(obj, id);\r\n objects.set(id, normalized);\r\n objectEntries.push({ id, node: normalized, source: \"Objects\", legacyName, synthetic: false });\r\n\r\n if (obj.name === \"Model\" && getPropertyValue<string>(obj, 1) === \"Mesh\") {\r\n const geometryId = getSyntheticLegacyId(\"Geometry\", legacyName);\r\n const geometry = createLegacyGeometry(obj, geometryId);\r\n objects.set(geometryId, geometry);\r\n objectEntries.push({ id: geometryId, node: geometry, source: \"legacySyntheticGeometry\", legacyName, synthetic: true });\r\n addConnection(connections, childrenOf, parentOf, diagnostics, \"OO\", geometryId, id);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Parse connections\r\n const connectionsNode = findDocumentNode(doc, \"Connections\");\r\n if (connectionsNode) {\r\n for (const c of connectionsNode.children) {\r\n if (c.name !== \"C\" && c.name !== \"Connect\") {\r\n continue;\r\n }\r\n\r\n const connectionIndex = connectionEntries.length;\r\n const type = getPropertyValue<string>(c, 0);\r\n const childIdRaw = c.properties[1]?.value;\r\n const parentIdRaw = c.properties[2]?.value;\r\n const entry: FBXConnectionEntry = {\r\n source: c.name,\r\n rawType: type,\r\n accepted: false,\r\n };\r\n connectionEntries.push(entry);\r\n\r\n if (type !== \"OO\" && type !== \"OP\") {\r\n const childId = childIdRaw === undefined ? undefined : toObjectId(childIdRaw, legacyIds);\r\n const parentId = parentIdRaw === undefined ? undefined : toObjectId(parentIdRaw, legacyIds);\r\n diagnostics.push({\r\n reason: \"unsupported-connection-type\",\r\n message: `Unsupported FBX connection type '${type ?? \"\"}' was not added to the graph.`,\r\n connectionIndex,\r\n type,\r\n childId,\r\n parentId,\r\n });\r\n continue;\r\n }\r\n\r\n if (childIdRaw === undefined || parentIdRaw === undefined) {\r\n diagnostics.push({\r\n reason: \"missing-connection-endpoint\",\r\n message: \"FBX connection is missing a child or parent endpoint.\",\r\n connectionIndex,\r\n type,\r\n });\r\n continue;\r\n }\r\n\r\n const childId = toObjectId(childIdRaw, legacyIds);\r\n const parentId = toObjectId(parentIdRaw, legacyIds);\r\n if (childId === undefined || parentId === undefined) {\r\n diagnostics.push({\r\n reason: \"unresolved-legacy-endpoint\",\r\n message: \"FBX connection references a legacy string endpoint that is not present in the object table.\",\r\n connectionIndex,\r\n type,\r\n });\r\n continue;\r\n }\r\n\r\n const propertyName = type === \"OP\" && c.properties.length > 3 ? getPropertyValue<string>(c, 3) : undefined;\r\n\r\n entry.childId = childId;\r\n entry.parentId = parentId;\r\n entry.propertyName = propertyName;\r\n\r\n if (childId === parentId) {\r\n diagnostics.push({\r\n reason: \"self-loop\",\r\n message: \"FBX connection references the same object as child and parent.\",\r\n connectionIndex,\r\n type,\r\n childId,\r\n parentId,\r\n propertyName,\r\n });\r\n }\r\n if (!objects.has(childId)) {\r\n diagnostics.push({\r\n reason: \"unresolved-object-reference\",\r\n message: \"FBX connection child ID is not present in the object table.\",\r\n connectionIndex,\r\n type,\r\n childId,\r\n parentId,\r\n propertyName,\r\n });\r\n }\r\n if (parentId !== 0 && !objects.has(parentId)) {\r\n diagnostics.push({\r\n reason: \"unresolved-object-reference\",\r\n message: \"FBX connection parent ID is not present in the object table.\",\r\n connectionIndex,\r\n type,\r\n childId,\r\n parentId,\r\n propertyName,\r\n });\r\n }\r\n\r\n addConnection(connections, childrenOf, parentOf, diagnostics, type, childId, parentId, propertyName, connectionIndex);\r\n entry.accepted = true;\r\n }\r\n }\r\n\r\n return { objects, objectEntries, childrenOf, parentOf, connections, connectionEntries, diagnostics };\r\n}\r\n\r\n/** Get all child objects of a given parent ID, optionally filtered by node name */\r\nexport function getChildren(map: FBXObjectMap, parentId: number, nodeName?: string): { id: number; node: FBXNode; propertyName?: string }[] {\r\n const children = map.childrenOf.get(parentId) ?? [];\r\n const result: { id: number; node: FBXNode; propertyName?: string }[] = [];\r\n\r\n for (const child of children) {\r\n const node = map.objects.get(child.id);\r\n if (node && (!nodeName || node.name === nodeName)) {\r\n result.push({ id: child.id, node, propertyName: child.propertyName });\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction toObjectNumber(value: unknown): number | undefined {\r\n return getSafeFBXObjectId(value);\r\n}\r\n\r\nfunction toObjectId(value: unknown, legacyIds: Map<string, number>): number | undefined {\r\n const numericId = toObjectNumber(value);\r\n if (numericId !== undefined) {\r\n return numericId;\r\n }\r\n if (typeof value !== \"string\") {\r\n return undefined;\r\n }\r\n const legacyName = cleanFBXName(value);\r\n if (legacyName === \"Scene\") {\r\n return 0;\r\n }\r\n return legacyIds.get(legacyName);\r\n}\r\n\r\nfunction addConnection(\r\n connections: FBXConnection[],\r\n childrenOf: Map<number, { id: number; propertyName?: string }[]>,\r\n parentOf: Map<number, { id: number; propertyName?: string }>,\r\n diagnostics: FBXConnectionDiagnostic[],\r\n type: ConnectionType,\r\n childId: number,\r\n parentId: number,\r\n propertyName?: string,\r\n connectionIndex?: number\r\n): void {\r\n connections.push({ type, childId, parentId, propertyName });\r\n\r\n if (!childrenOf.has(parentId)) {\r\n childrenOf.set(parentId, []);\r\n }\r\n childrenOf.get(parentId)!.push({ id: childId, propertyName });\r\n const existingParent = parentOf.get(childId);\r\n if (existingParent) {\r\n diagnostics.push({\r\n reason: \"duplicate-parent\",\r\n message: \"FBX object has multiple parents; preserving the existing last-parent behavior.\",\r\n connectionIndex,\r\n type,\r\n childId,\r\n parentId,\r\n propertyName,\r\n });\r\n }\r\n parentOf.set(childId, { id: parentId, propertyName });\r\n}\r\n\r\nfunction normalizeLegacyObject(node: FBXNode, id: number): FBXNode {\r\n const name = cleanFBXName(getPropertyValue<string>(node, 0) ?? node.name);\r\n const subType = getPropertyValue<string>(node, 1) ?? \"\";\r\n return {\r\n ...node,\r\n properties: [\r\n { type: \"int64\", value: id },\r\n { type: \"string\", value: name },\r\n { type: \"string\", value: subType },\r\n ],\r\n };\r\n}\r\n\r\nfunction createLegacyGeometry(modelNode: FBXNode, geometryId: number): FBXNode {\r\n const name = cleanFBXName(getPropertyValue<string>(modelNode, 0) ?? \"Geometry\");\r\n return {\r\n name: \"Geometry\",\r\n properties: [\r\n { type: \"int64\", value: geometryId },\r\n { type: \"string\", value: name },\r\n { type: \"string\", value: \"Mesh\" },\r\n ],\r\n children: modelNode.children,\r\n };\r\n}\r\n"]}
1
+ {"version":3,"file":"connections.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/interpreter/connections.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,OAAO,EAAoD,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAuF3J;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAgB;IAC/C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;IAC3C,MAAM,aAAa,GAAqB,EAAE,CAAC;IAC3C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAmD,CAAC;IAC9E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAiD,CAAC;IAC1E,MAAM,WAAW,GAAoB,EAAE,CAAC;IACxC,MAAM,iBAAiB,GAAyB,EAAE,CAAC;IACnD,MAAM,WAAW,GAA8B,EAAE,CAAC;IAClD,6GAA6G;IAC7G,2GAA2G;IAC3G,0DAA0D;IAC1D,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvD,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAA+B,CAAC;IAClE,MAAM,uBAAuB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE1D,4GAA4G;IAC5G,0EAA0E;IAC1E,MAAM,WAAW,GAAG,gBAAgB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACrD,MAAM,eAAe,GAAG,gBAAgB,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,OAAO,GAAG,CAAC,QAAiC,EAAQ,EAAE;QACxD,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,CAAC;QAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACL,CAAC,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,QAAQ,IAAI,EAAE,EAAE,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,QAAQ,IAAI,EAAE,EAAE,CAAC;QAC9C,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,eAAe,GAAG,CAAC,CAAC,CAAC;IACzB,MAAM,UAAU,GAAG,GAAW,EAAE;QAC5B,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;YAClC,eAAe,EAAE,CAAC;QACtB,CAAC;QACD,MAAM,EAAE,GAAG,eAAe,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,EAAE,CAAC;IACd,CAAC,CAAC;IACF,2GAA2G;IAC3G,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC9C,MAAM,WAAW,GAAG,CAAC,QAAiC,EAAsB,EAAE;QAC1E,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,IAAI,QAAQ,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACvC,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;gBACnB,EAAE,GAAG,UAAU,EAAE,CAAC;gBAClB,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACtC,CAAC;YACD,OAAO,EAAE,CAAC;QACd,CAAC;QACD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC,CAAC;IACF,MAAM,UAAU,GAAG,CAAC,QAAiC,EAAsB,EAAE;QACzE,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,CAAC;QAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC5B,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,MAAM,CAAC;QAClB,CAAC;QACD,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;YACzB,OAAO,CAAC,CAAC;QACb,CAAC;QACD,OAAO,oBAAoB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAChD,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,OAAe,EAAU,EAAE;QAC5C,IAAI,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACnB,EAAE,GAAG,UAAU,EAAE,CAAC;YAClB,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC3B,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;YACpC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACnC,oBAAoB,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACxC,CAAC;QACL,CAAC;QACD,OAAO,EAAE,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAAE,IAAY,EAAU,EAAE;QAChE,IAAI,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,SAAS,EAAE,CAAC;YACb,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC;YACtB,kBAAkB,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACnB,EAAE,GAAG,UAAU,EAAE,CAAC;YAClB,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO,EAAE,CAAC;IACd,CAAC,CAAC;IAEF,gHAAgH;IAChH,MAAM,sBAAsB,GAAG,CAAC,KAAc,EAAE,UAAkB,EAAE,GAAW,EAAQ,EAAE;QACrF,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;QAChE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO;QACX,CAAC;QACD,MAAM,UAAU,GAAG,oBAAoB,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,aAAa,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,YAAY,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACtI,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAClC,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,2BAA2B,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9H,aAAa,CAAC,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;QAC5F,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACzB,MAAM,SAAS,GAAG,YAAY,CAAC,gBAAgB,CAAS,KAAK,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC;YAC9E,MAAM,SAAS,GAAG,oBAAoB,CAAC,mBAAmB,EAAE,GAAG,GAAG,IAAI,SAAS,EAAE,CAAC,CAAC;YACnF,MAAM,OAAO,GAAG,kBAAkB,CAAC,UAAU,EAAE,SAAS,EAAE,gBAAgB,SAAS,EAAE,EAAE,mBAAmB,EAAE;gBACxG,iBAAiB,CAAC,GAAG,CAAC;gBACtB,EAAE,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;gBACpF;oBACI,IAAI,EAAE,cAAc;oBACpB,UAAU,EAAE,EAAE;oBACd,QAAQ,EAAE;wBACN;4BACI,IAAI,EAAE,UAAU;4BAChB,UAAU,EAAE;gCACR,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE;gCAC1C,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;gCACnC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;gCAC9B,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE;6BAChC;4BACD,QAAQ,EAAE,EAAE;yBACf;qBACJ;iBACJ;aACJ,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAChC,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,2BAA2B,EAAE,UAAU,EAAE,GAAG,GAAG,IAAI,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9I,aAAa,CAAC,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YAC3F,MAAM,OAAO,GAAG,oBAAoB,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,SAAS,EAAE,CAAC,CAAC;YACrE,MAAM,aAAa,GAAG,kBAAkB,CAAC,UAAU,EAAE,OAAO,EAAE,aAAa,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;YACjH,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YACpC,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,2BAA2B,EAAE,UAAU,EAAE,GAAG,GAAG,IAAI,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAClJ,aAAa,CAAC,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QAC5F,CAAC;IACL,CAAC,CAAC;IAEF,wCAAwC;IACxC,IAAI,WAAW,EAAE,CAAC;QACd,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YACjC,IAAI,MAAM,EAAE,CAAC;gBACT,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;gBAC/B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;oBACnB,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;oBACrB,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;oBAC3E,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,gBAAgB,CAAS,GAAG,EAAE,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;wBACzE,sEAAsE;wBACtE,sBAAsB,CAAC,GAAG,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;oBAChD,CAAC;gBACL,CAAC;qBAAM,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC;oBAChC,MAAM,EAAE,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;oBACnC,MAAM,UAAU,GAAG,qBAAqB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;oBAClD,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;oBAC5B,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;oBAE9F,MAAM,aAAa,GAAG,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAS,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;oBAC1F,IAAI,aAAa,KAAK,MAAM,EAAE,CAAC;wBAC3B,MAAM,UAAU,GAAG,oBAAoB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;wBAChE,MAAM,QAAQ,GAAG,oBAAoB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;wBACvD,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;wBAClC,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,yBAAyB,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;wBACvH,aAAa,CAAC,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;wBACpF,uBAAuB,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;wBAE5C,iGAAiG;wBACjG,sBAAsB,CAAC,GAAG,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;oBACxD,CAAC;yBAAM,IAAI,aAAa,KAAK,OAAO,IAAI,aAAa,KAAK,QAAQ,EAAE,CAAC;wBACjE,uGAAuG;wBACvG,MAAM,WAAW,GAAG,oBAAoB,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;wBACtE,MAAM,SAAS,GAAG,kBAAkB,CAAC,eAAe,EAAE,WAAW,EAAE,kBAAkB,YAAY,CAAC,UAAU,CAAC,EAAE,EAAE,aAAa,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;wBAC9I,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;wBACpC,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,0BAA0B,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;wBAC1H,aAAa,CAAC,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;oBACzF,CAAC;gBACL,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;IAED,oBAAoB;IACpB,IAAI,eAAe,EAAE,CAAC;QAClB,KAAK,MAAM,CAAC,IAAI,eAAe,CAAC,QAAQ,EAAE,CAAC;YACvC,IAAI,CAAC,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACzC,SAAS;YACb,CAAC;YAED,MAAM,eAAe,GAAG,iBAAiB,CAAC,MAAM,CAAC;YACjD,IAAI,IAAI,GAAG,gBAAgB,CAAS,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1C,IAAI,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YACjC,IAAI,WAAW,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,cAAkC,CAAC;YACvC,gGAAgG;YAChG,yGAAyG;YACzG,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzF,IAAI,GAAG,IAAI,CAAC;gBACZ,cAAc,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAe,CAAC;gBACjD,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBAC7B,WAAW,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAClC,CAAC;YACD,MAAM,KAAK,GAAuB;gBAC9B,MAAM,EAAE,CAAC,CAAC,IAAI;gBACd,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,KAAK;aAClB,CAAC;YACF,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAE9B,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBACjC,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;gBACvC,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;gBACzC,WAAW,CAAC,IAAI,CAAC;oBACb,MAAM,EAAE,6BAA6B;oBACrC,OAAO,EAAE,oCAAoC,IAAI,IAAI,EAAE,+BAA+B;oBACtF,eAAe;oBACf,IAAI;oBACJ,OAAO;oBACP,QAAQ;iBACX,CAAC,CAAC;gBACH,SAAS;YACb,CAAC;YAED,IAAI,UAAU,KAAK,SAAS,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;gBACxD,WAAW,CAAC,IAAI,CAAC;oBACb,MAAM,EAAE,6BAA6B;oBACrC,OAAO,EAAE,uDAAuD;oBAChE,eAAe;oBACf,IAAI;iBACP,CAAC,CAAC;gBACH,SAAS;YACb,CAAC;YAED,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YACvC,IAAI,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;YACvC,iFAAiF;YACjF,IAAI,OAAO,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC/F,QAAQ,GAAG,uBAAuB,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC;YACjE,CAAC;YACD,IAAI,OAAO,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAClD,WAAW,CAAC,IAAI,CAAC;oBACb,MAAM,EAAE,4BAA4B;oBACpC,OAAO,EAAE,6FAA6F;oBACtG,eAAe;oBACf,IAAI;iBACP,CAAC,CAAC;gBACH,SAAS;YACb,CAAC;YAED,MAAM,YAAY,GAAG,cAAc,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAE/H,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;YACxB,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAC1B,KAAK,CAAC,YAAY,GAAG,YAAY,CAAC;YAElC,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACvB,WAAW,CAAC,IAAI,CAAC;oBACb,MAAM,EAAE,WAAW;oBACnB,OAAO,EAAE,gEAAgE;oBACzE,eAAe;oBACf,IAAI;oBACJ,OAAO;oBACP,QAAQ;oBACR,YAAY;iBACf,CAAC,CAAC;YACP,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxB,WAAW,CAAC,IAAI,CAAC;oBACb,MAAM,EAAE,6BAA6B;oBACrC,OAAO,EAAE,6DAA6D;oBACtE,eAAe;oBACf,IAAI;oBACJ,OAAO;oBACP,QAAQ;oBACR,YAAY;iBACf,CAAC,CAAC;YACP,CAAC;YACD,IAAI,QAAQ,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC3C,WAAW,CAAC,IAAI,CAAC;oBACb,MAAM,EAAE,6BAA6B;oBACrC,OAAO,EAAE,8DAA8D;oBACvE,eAAe;oBACf,IAAI;oBACJ,OAAO;oBACP,QAAQ;oBACR,YAAY;iBACf,CAAC,CAAC;YACP,CAAC;YAED,aAAa,CAAC,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC;YACtH,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC1B,CAAC;IACL,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,CAAC;AACzG,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,WAAW,CAAC,GAAiB,EAAE,QAAgB,EAAE,QAAiB;IAC9E,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACpD,MAAM,MAAM,GAA2D,EAAE,CAAC;IAE1E,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACvC,IAAI,IAAI,IAAI,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC;YAChD,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC;QAC1E,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe;IACtC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAC9F,CAAC;AAED,SAAS,kBAAkB,CAAC,QAAgB,EAAE,EAAU,EAAE,IAAY,EAAE,OAAe,EAAE,QAAmB;IACxG,OAAO;QACH,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACR,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;YAC5B,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;YAC/B,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE;SACrC;QACD,QAAQ;KACX,CAAC;AACN,CAAC;AAED,SAAS,aAAa,CAClB,WAA4B,EAC5B,UAAgE,EAChE,QAA4D,EAC5D,WAAsC,EACtC,IAAoB,EACpB,OAAe,EACf,QAAgB,EAChB,YAAqB,EACrB,eAAwB;IAExB,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;IAE5D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACjC,CAAC;IACD,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,cAAc,EAAE,CAAC;QACjB,WAAW,CAAC,IAAI,CAAC;YACb,MAAM,EAAE,kBAAkB;YAC1B,OAAO,EAAE,gFAAgF;YACzF,eAAe;YACf,IAAI;YACJ,OAAO;YACP,QAAQ;YACR,YAAY;SACf,CAAC,CAAC;IACP,CAAC;IACD,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAa,EAAE,EAAU;IACpD,MAAM,IAAI,GAAG,YAAY,CAAC,gBAAgB,CAAS,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1E,MAAM,OAAO,GAAG,gBAAgB,CAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxD,OAAO;QACH,GAAG,IAAI;QACP,UAAU,EAAE;YACR,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;YAC5B,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;YAC/B,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE;SACrC;KACJ,CAAC;AACN,CAAC;AAED,SAAS,oBAAoB,CAAC,SAAkB,EAAE,UAAkB;IAChE,MAAM,IAAI,GAAG,YAAY,CAAC,gBAAgB,CAAS,SAAS,EAAE,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC;IAChF,OAAO;QACH,IAAI,EAAE,UAAU;QAChB,UAAU,EAAE;YACR,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE;YACpC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;YAC/B,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE;SACpC;QACD,QAAQ,EAAE,SAAS,CAAC,QAAQ;KAC/B,CAAC;AACN,CAAC","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\nimport { type FBXDocument, type FBXNode, type FBXProperty, cleanFBXName, findDocumentNode, getPropertyValue, getSafeFBXObjectId } from \"../types/fbxTypes\";\n\n/** Connection type: OO = object-to-object, OP = object-to-property */\nexport type ConnectionType = \"OO\" | \"OP\";\n\n/** A resolved FBX object connection. */\nexport interface FBXConnection {\n /** Connection type. */\n type: ConnectionType;\n /** Child object ID. */\n childId: number;\n /** Parent object ID. */\n parentId: number;\n /** For OP connections, the property name on the parent (e.g. \"DiffuseColor\") */\n propertyName?: string;\n}\n\n/** Object table entry used by the FBX connection graph. */\nexport interface FBXObjectEntry {\n /** Object ID. */\n id: number;\n /** Object node. */\n node: FBXNode;\n /** Source of the object entry. */\n source: \"Objects\" | \"legacySyntheticGeometry\" | \"legacySyntheticAttribute\" | \"legacySyntheticBlendShape\";\n /** Legacy string object name, when applicable. */\n legacyName?: string;\n /** True if the object was synthesized for legacy compatibility. */\n synthetic: boolean;\n}\n\n/** Raw connection-table entry and import status. */\nexport interface FBXConnectionEntry {\n /** Source node name. */\n source: \"C\" | \"Connect\";\n /** Raw connection type. */\n rawType?: string;\n /** Child object ID, when resolved. */\n childId?: number;\n /** Parent object ID, when resolved. */\n parentId?: number;\n /** OP connection property name, when present. */\n propertyName?: string;\n /** True if the connection was accepted into the resolved graph. */\n accepted: boolean;\n}\n\n/** Reason a connection produced a diagnostic. */\nexport type FBXConnectionDiagnosticReason =\n \"unsupported-connection-type\" | \"missing-connection-endpoint\" | \"unresolved-legacy-endpoint\" | \"unresolved-object-reference\" | \"duplicate-parent\" | \"self-loop\";\n\n/** Recoverable connection graph issue. */\nexport interface FBXConnectionDiagnostic {\n /** Diagnostic reason. */\n reason: FBXConnectionDiagnosticReason;\n /** Human-readable diagnostic message. */\n message: string;\n /** Connection-table index associated with the diagnostic, if applicable. */\n connectionIndex?: number;\n /** Connection type associated with the diagnostic, if applicable. */\n type?: string;\n /** Child object ID associated with the diagnostic, if applicable. */\n childId?: number;\n /** Parent object ID associated with the diagnostic, if applicable. */\n parentId?: number;\n /** OP connection property name associated with the diagnostic, if applicable. */\n propertyName?: string;\n}\n\n/** Resolved FBX object and connection graph. */\nexport interface FBXObjectMap {\n /** All objects by their unique ID */\n objects: Map<number, FBXNode>;\n /** Object table entries, including synthetic compatibility objects */\n objectEntries: FBXObjectEntry[];\n /** Children of each object ID */\n childrenOf: Map<number, { id: number; propertyName?: string }[]>;\n /** Parent of each object ID */\n parentOf: Map<number, { id: number; propertyName?: string }>;\n /** Raw connection list */\n connections: FBXConnection[];\n /** Raw connection-table entries and whether they were accepted into the graph */\n connectionEntries: FBXConnectionEntry[];\n /** Unsupported or suspicious connection shapes encountered while preserving graph behavior */\n diagnostics: FBXConnectionDiagnostic[];\n}\n\n/**\n * Build a connection graph from a parsed FBX document.\n * Maps object IDs to their FBXNode and resolves parent-child relationships.\n */\nexport function resolveConnections(doc: FBXDocument): FBXObjectMap {\n const objects = new Map<number, FBXNode>();\n const objectEntries: FBXObjectEntry[] = [];\n const childrenOf = new Map<number, { id: number; propertyName?: string }[]>();\n const parentOf = new Map<number, { id: number; propertyName?: string }>();\n const connections: FBXConnection[] = [];\n const connectionEntries: FBXConnectionEntry[] = [];\n const diagnostics: FBXConnectionDiagnostic[] = [];\n // Legacy (6.x and older) objects are identified by their full \"Class::Name\" string, exactly as the SDK does,\n // so that a material, texture and video sharing a base name stay distinct. Connections that only carry the\n // bare name fall back to the first object with that name.\n const legacyIds = new Map<string, number>();\n const legacyIdsByCleanName = new Map<string, number>();\n const syntheticLegacyIds = new Map<string, Map<string, number>>();\n const legacyGeometryByModelId = new Map<number, number>();\n\n // Every numeric id the file uses is reserved up front so that synthetic ids (legacy objects, inline shapes)\n // and the stand-ins for ids beyond 2^53 never collide with a real object.\n const objectsNode = findDocumentNode(doc, \"Objects\");\n const connectionsNode = findDocumentNode(doc, \"Connections\");\n const usedIds = new Set<number>();\n const reserve = (property: FBXProperty | undefined): void => {\n const value = property?.value;\n if (typeof value === \"number\" && Number.isSafeInteger(value)) {\n usedIds.add(value);\n }\n };\n for (const obj of objectsNode?.children ?? []) {\n reserve(obj.properties[0]);\n }\n for (const c of connectionsNode?.children ?? []) {\n reserve(c.properties[1]);\n reserve(c.properties[2]);\n reserve(c.properties[3]);\n }\n let nextSyntheticId = -1;\n const allocateId = (): number => {\n while (usedIds.has(nextSyntheticId)) {\n nextSyntheticId--;\n }\n const id = nextSyntheticId--;\n usedIds.add(id);\n return id;\n };\n // Ids whose magnitude exceeds 2^53 are keyed by their exact decimal text; distinct texts get distinct ids.\n const remappedIds = new Map<string, number>();\n const numericIdOf = (property: FBXProperty | undefined): number | undefined => {\n if (!property) {\n return undefined;\n }\n if (property.raw !== undefined) {\n let id = remappedIds.get(property.raw);\n if (id === undefined) {\n id = allocateId();\n remappedIds.set(property.raw, id);\n }\n return id;\n }\n return getSafeFBXObjectId(property.value);\n };\n const toObjectId = (property: FBXProperty | undefined): number | undefined => {\n const numericId = numericIdOf(property);\n if (numericId !== undefined) {\n return numericId;\n }\n const value = property?.value;\n if (typeof value !== \"string\") {\n return undefined;\n }\n const direct = legacyIds.get(value);\n if (direct !== undefined) {\n return direct;\n }\n const legacyName = cleanFBXName(value);\n if (legacyName === \"Scene\") {\n return 0;\n }\n return legacyIdsByCleanName.get(legacyName);\n };\n\n const getLegacyId = (rawName: string): number => {\n let id = legacyIds.get(rawName);\n if (id === undefined) {\n id = allocateId();\n legacyIds.set(rawName, id);\n const clean = cleanFBXName(rawName);\n if (!legacyIdsByCleanName.has(clean)) {\n legacyIdsByCleanName.set(clean, id);\n }\n }\n return id;\n };\n\n const getSyntheticLegacyId = (role: string, name: string): number => {\n let idsByName = syntheticLegacyIds.get(role);\n if (!idsByName) {\n idsByName = new Map();\n syntheticLegacyIds.set(role, idsByName);\n }\n\n let id = idsByName.get(name);\n if (id === undefined) {\n id = allocateId();\n idsByName.set(name, id);\n }\n return id;\n };\n\n /** Turns `Shape` children of a geometry into a BlendShape deformer with one channel and shape geometry each. */\n const synthesizeInlineShapes = (owner: FBXNode, geometryId: number, key: string): void => {\n const shapes = owner.children.filter((c) => c.name === \"Shape\");\n if (shapes.length === 0) {\n return;\n }\n const deformerId = getSyntheticLegacyId(\"BlendShape\", key);\n const deformer = createLegacyObject(\"Deformer\", deformerId, `Deformer::${cleanFBXName(key)}`, \"BlendShape\", [createVersionNode(100)]);\n objects.set(deformerId, deformer);\n objectEntries.push({ id: deformerId, node: deformer, source: \"legacySyntheticBlendShape\", legacyName: key, synthetic: true });\n addConnection(connections, childrenOf, parentOf, diagnostics, \"OO\", deformerId, geometryId);\n for (const shape of shapes) {\n const shapeName = cleanFBXName(getPropertyValue<string>(shape, 0) ?? \"Shape\");\n const channelId = getSyntheticLegacyId(\"BlendShapeChannel\", `${key}|${shapeName}`);\n const channel = createLegacyObject(\"Deformer\", channelId, `SubDeformer::${shapeName}`, \"BlendShapeChannel\", [\n createVersionNode(100),\n { name: \"DeformPercent\", properties: [{ type: \"float64\", value: 0 }], children: [] },\n {\n name: \"Properties60\",\n properties: [],\n children: [\n {\n name: \"Property\",\n properties: [\n { type: \"string\", value: \"DeformPercent\" },\n { type: \"string\", value: \"Number\" },\n { type: \"string\", value: \"A\" },\n { type: \"float64\", value: 0 },\n ],\n children: [],\n },\n ],\n },\n ]);\n objects.set(channelId, channel);\n objectEntries.push({ id: channelId, node: channel, source: \"legacySyntheticBlendShape\", legacyName: `${key}|${shapeName}`, synthetic: true });\n addConnection(connections, childrenOf, parentOf, diagnostics, \"OO\", channelId, deformerId);\n const shapeId = getSyntheticLegacyId(\"Shape\", `${key}|${shapeName}`);\n const shapeGeometry = createLegacyObject(\"Geometry\", shapeId, `Geometry::${shapeName}`, \"Shape\", shape.children);\n objects.set(shapeId, shapeGeometry);\n objectEntries.push({ id: shapeId, node: shapeGeometry, source: \"legacySyntheticBlendShape\", legacyName: `${key}|${shapeName}`, synthetic: true });\n addConnection(connections, childrenOf, parentOf, diagnostics, \"OO\", shapeId, channelId);\n }\n };\n\n // Build object map from Objects section\n if (objectsNode) {\n for (const obj of objectsNode.children) {\n const idProp = obj.properties[0];\n if (idProp) {\n const id = numericIdOf(idProp);\n if (id !== undefined) {\n objects.set(id, obj);\n objectEntries.push({ id, node: obj, source: \"Objects\", synthetic: false });\n if (obj.name === \"Geometry\" && getPropertyValue<string>(obj, 2) === \"Mesh\") {\n // FBX 7.1 stores blend shapes inline in the geometry, like 6.x files.\n synthesizeInlineShapes(obj, id, String(id));\n }\n } else if (typeof idProp.value === \"string\") {\n const legacyName = idProp.value;\n const id = getLegacyId(legacyName);\n const normalized = normalizeLegacyObject(obj, id);\n objects.set(id, normalized);\n objectEntries.push({ id, node: normalized, source: \"Objects\", legacyName, synthetic: false });\n\n const legacySubType = obj.name === \"Model\" ? getPropertyValue<string>(obj, 1) : undefined;\n if (legacySubType === \"Mesh\") {\n const geometryId = getSyntheticLegacyId(\"Geometry\", legacyName);\n const geometry = createLegacyGeometry(obj, geometryId);\n objects.set(geometryId, geometry);\n objectEntries.push({ id: geometryId, node: geometry, source: \"legacySyntheticGeometry\", legacyName, synthetic: true });\n addConnection(connections, childrenOf, parentOf, diagnostics, \"OO\", geometryId, id);\n legacyGeometryByModelId.set(id, geometryId);\n\n // Inline blend shapes become a BlendShape deformer with one channel and one shape geometry each.\n synthesizeInlineShapes(obj, geometryId, legacyName);\n } else if (legacySubType === \"Light\" || legacySubType === \"Camera\") {\n // 6.x lights and cameras keep their attribute properties on the model; expose them as a NodeAttribute.\n const attributeId = getSyntheticLegacyId(\"NodeAttribute\", legacyName);\n const attribute = createLegacyObject(\"NodeAttribute\", attributeId, `NodeAttribute::${cleanFBXName(legacyName)}`, legacySubType, obj.children);\n objects.set(attributeId, attribute);\n objectEntries.push({ id: attributeId, node: attribute, source: \"legacySyntheticAttribute\", legacyName, synthetic: true });\n addConnection(connections, childrenOf, parentOf, diagnostics, \"OO\", attributeId, id);\n }\n }\n }\n }\n }\n\n // Parse connections\n if (connectionsNode) {\n for (const c of connectionsNode.children) {\n if (c.name !== \"C\" && c.name !== \"Connect\") {\n continue;\n }\n\n const connectionIndex = connectionEntries.length;\n let type = getPropertyValue<string>(c, 0);\n let childIdRaw = c.properties[1];\n let parentIdRaw = c.properties[2];\n let poPropertyName: string | undefined;\n // \"PO\" connects a property of the first object to the second object (6.x constraints use it for\n // \"Constrained Object\"); it is the mirror image of \"OP\", so store it as OP from the object to the owner.\n if (type === \"PO\" && typeof c.properties[2]?.value === \"string\" && c.properties.length > 3) {\n type = \"OP\";\n poPropertyName = c.properties[2].value as string;\n childIdRaw = c.properties[3];\n parentIdRaw = c.properties[1];\n }\n const entry: FBXConnectionEntry = {\n source: c.name,\n rawType: type,\n accepted: false,\n };\n connectionEntries.push(entry);\n\n if (type !== \"OO\" && type !== \"OP\") {\n const childId = toObjectId(childIdRaw);\n const parentId = toObjectId(parentIdRaw);\n diagnostics.push({\n reason: \"unsupported-connection-type\",\n message: `Unsupported FBX connection type '${type ?? \"\"}' was not added to the graph.`,\n connectionIndex,\n type,\n childId,\n parentId,\n });\n continue;\n }\n\n if (childIdRaw === undefined || parentIdRaw === undefined) {\n diagnostics.push({\n reason: \"missing-connection-endpoint\",\n message: \"FBX connection is missing a child or parent endpoint.\",\n connectionIndex,\n type,\n });\n continue;\n }\n\n const childId = toObjectId(childIdRaw);\n let parentId = toObjectId(parentIdRaw);\n // 6.x deformers connect to the model; the importer expects them on the geometry.\n if (childId !== undefined && parentId !== undefined && objects.get(childId)?.name === \"Deformer\") {\n parentId = legacyGeometryByModelId.get(parentId) ?? parentId;\n }\n if (childId === undefined || parentId === undefined) {\n diagnostics.push({\n reason: \"unresolved-legacy-endpoint\",\n message: \"FBX connection references a legacy string endpoint that is not present in the object table.\",\n connectionIndex,\n type,\n });\n continue;\n }\n\n const propertyName = poPropertyName ?? (type === \"OP\" && c.properties.length > 3 ? getPropertyValue<string>(c, 3) : undefined);\n\n entry.childId = childId;\n entry.parentId = parentId;\n entry.propertyName = propertyName;\n\n if (childId === parentId) {\n diagnostics.push({\n reason: \"self-loop\",\n message: \"FBX connection references the same object as child and parent.\",\n connectionIndex,\n type,\n childId,\n parentId,\n propertyName,\n });\n }\n if (!objects.has(childId)) {\n diagnostics.push({\n reason: \"unresolved-object-reference\",\n message: \"FBX connection child ID is not present in the object table.\",\n connectionIndex,\n type,\n childId,\n parentId,\n propertyName,\n });\n }\n if (parentId !== 0 && !objects.has(parentId)) {\n diagnostics.push({\n reason: \"unresolved-object-reference\",\n message: \"FBX connection parent ID is not present in the object table.\",\n connectionIndex,\n type,\n childId,\n parentId,\n propertyName,\n });\n }\n\n addConnection(connections, childrenOf, parentOf, diagnostics, type, childId, parentId, propertyName, connectionIndex);\n entry.accepted = true;\n }\n }\n\n return { objects, objectEntries, childrenOf, parentOf, connections, connectionEntries, diagnostics };\n}\n\n/** Get all child objects of a given parent ID, optionally filtered by node name */\nexport function getChildren(map: FBXObjectMap, parentId: number, nodeName?: string): { id: number; node: FBXNode; propertyName?: string }[] {\n const children = map.childrenOf.get(parentId) ?? [];\n const result: { id: number; node: FBXNode; propertyName?: string }[] = [];\n\n for (const child of children) {\n const node = map.objects.get(child.id);\n if (node && (!nodeName || node.name === nodeName)) {\n result.push({ id: child.id, node, propertyName: child.propertyName });\n }\n }\n\n return result;\n}\n\nfunction createVersionNode(version: number): FBXNode {\n return { name: \"Version\", properties: [{ type: \"int32\", value: version }], children: [] };\n}\n\nfunction createLegacyObject(nodeName: string, id: number, name: string, subType: string, children: FBXNode[]): FBXNode {\n return {\n name: nodeName,\n properties: [\n { type: \"int64\", value: id },\n { type: \"string\", value: name },\n { type: \"string\", value: subType },\n ],\n children,\n };\n}\n\nfunction addConnection(\n connections: FBXConnection[],\n childrenOf: Map<number, { id: number; propertyName?: string }[]>,\n parentOf: Map<number, { id: number; propertyName?: string }>,\n diagnostics: FBXConnectionDiagnostic[],\n type: ConnectionType,\n childId: number,\n parentId: number,\n propertyName?: string,\n connectionIndex?: number\n): void {\n connections.push({ type, childId, parentId, propertyName });\n\n if (!childrenOf.has(parentId)) {\n childrenOf.set(parentId, []);\n }\n childrenOf.get(parentId)!.push({ id: childId, propertyName });\n const existingParent = parentOf.get(childId);\n if (existingParent) {\n diagnostics.push({\n reason: \"duplicate-parent\",\n message: \"FBX object has multiple parents; preserving the existing last-parent behavior.\",\n connectionIndex,\n type,\n childId,\n parentId,\n propertyName,\n });\n }\n parentOf.set(childId, { id: parentId, propertyName });\n}\n\nfunction normalizeLegacyObject(node: FBXNode, id: number): FBXNode {\n const name = cleanFBXName(getPropertyValue<string>(node, 0) ?? node.name);\n const subType = getPropertyValue<string>(node, 1) ?? \"\";\n return {\n ...node,\n properties: [\n { type: \"int64\", value: id },\n { type: \"string\", value: name },\n { type: \"string\", value: subType },\n ],\n };\n}\n\nfunction createLegacyGeometry(modelNode: FBXNode, geometryId: number): FBXNode {\n const name = cleanFBXName(getPropertyValue<string>(modelNode, 0) ?? \"Geometry\");\n return {\n name: \"Geometry\",\n properties: [\n { type: \"int64\", value: geometryId },\n { type: \"string\", value: name },\n { type: \"string\", value: \"Mesh\" },\n ],\n children: modelNode.children,\n };\n}\n"]}
@@ -0,0 +1,68 @@
1
+ import { type FBXObjectMap } from "./connections.js";
2
+ export type FBXConstraintType = "aim" | "parent" | "position" | "rotation" | "scale" | "singleChainIK" | "unknown";
3
+ export type Vec3 = [number, number, number];
4
+ export type Bool3 = [boolean, boolean, boolean];
5
+ /** One weighted target of a constraint. */
6
+ export interface FBXConstraintTarget {
7
+ /** Model id of the target node */
8
+ modelId: number;
9
+ /** Normalized weight (file value / 100, or as-is for IK pole targets) */
10
+ weight: number;
11
+ /** Parent constraint translation offset expressed in the target's space */
12
+ offsetTranslation: Vec3;
13
+ /** Parent constraint rotation offset in degrees, expressed in the target's space */
14
+ offsetRotation: Vec3;
15
+ /** Parent constraint scale offset expressed in the target's space */
16
+ offsetScale: Vec3;
17
+ }
18
+ /** A constraint object of the file, with its targets and parameters resolved. */
19
+ export interface FBXConstraintData {
20
+ /** Constraint object id */
21
+ id: number;
22
+ /** Constraint name */
23
+ name: string;
24
+ /** Resolved constraint kind */
25
+ type: FBXConstraintType;
26
+ /** Constraint type name as written in the file (e.g. "Parent-Child") */
27
+ typeName: string;
28
+ /** Constrained model */
29
+ nodeId?: number;
30
+ /** Weighted targets in file order */
31
+ targets: FBXConstraintTarget[];
32
+ /** Global weight (file value / 100) */
33
+ weight: number;
34
+ /** False when the constraint is switched off in the file */
35
+ active: boolean;
36
+ /** Which translation axes the constraint drives */
37
+ affectTranslation: Bool3;
38
+ /** Which rotation axes the constraint drives */
39
+ affectRotation: Bool3;
40
+ /** Which scale axes the constraint drives */
41
+ affectScale: Bool3;
42
+ /** Translation offset of the constrained node */
43
+ offsetTranslation: Vec3;
44
+ /** Rotation offset of the constrained node, in degrees */
45
+ offsetRotation: Vec3;
46
+ /** Scale offset of the constrained node */
47
+ offsetScale: Vec3;
48
+ /** Aim: local axis that points at the target */
49
+ aimVector: Vec3;
50
+ /** Aim: local axis aligned with the up direction */
51
+ upVector: Vec3;
52
+ /** Aim: world up direction (world up modes 2 and 3) */
53
+ worldUpVector: Vec3;
54
+ /** Aim: 0 scene up, 1 aim up node, 2 align to node, 3 vector, 4 none */
55
+ worldUpType: number;
56
+ /** Aim: model id of the world up object (world up modes 1 and 2) */
57
+ worldUpNodeId?: number;
58
+ /** Single chain IK: model id of the first joint of the chain */
59
+ ikFirstJointId?: number;
60
+ /** Single chain IK: model id of the last joint of the chain */
61
+ ikEndJointId?: number;
62
+ /** Single chain IK: model id of the effector */
63
+ ikEffectorId?: number;
64
+ /** Single chain IK: pole vector */
65
+ ikPoleVector: Vec3;
66
+ }
67
+ /** Reads every constraint object of the scene. */
68
+ export declare function extractConstraints(objectMap: FBXObjectMap): FBXConstraintData[];
@@ -0,0 +1,143 @@
1
+ /* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */
2
+ /**
3
+ * FBX constraints (FbxConstraint): aim, parent, position, rotation, scale and single chain IK. The property and
4
+ * connection conventions follow the FBX SDK (target weights are `<TargetName>.Weight`, parent offsets
5
+ * `<TargetName>.Offset T/R/S`, the constrained node arrives through the "Constrained Object" connection).
6
+ */
7
+ import { getPropertyValue, cleanFBXName } from "../types/fbxTypes.js";
8
+ import { getPropertyEntries } from "./propertyTemplates.js";
9
+ const TYPE_NAMES = {
10
+ Aim: "aim",
11
+ "Parent-Child": "parent",
12
+ "Position From Positions": "position",
13
+ "Rotation From Rotations": "rotation",
14
+ "Scale From Scales": "scale",
15
+ "Single Chain IK": "singleChainIK",
16
+ };
17
+ function vec3(values, fallback) {
18
+ if (values && typeof values[0] === "number" && typeof values[1] === "number" && typeof values[2] === "number") {
19
+ return [values[0], values[1], values[2]];
20
+ }
21
+ return fallback;
22
+ }
23
+ function num(values, fallback) {
24
+ const v = values?.[0];
25
+ return typeof v === "number" ? v : typeof v === "boolean" ? (v ? 1 : 0) : fallback;
26
+ }
27
+ /** Reads every constraint object of the scene. */
28
+ export function extractConstraints(objectMap) {
29
+ const constraints = [];
30
+ for (const [id, node] of Array.from(objectMap.objects)) {
31
+ if (node.name !== "Constraint") {
32
+ continue;
33
+ }
34
+ constraints.push(extractConstraint(id, node, objectMap));
35
+ }
36
+ return constraints;
37
+ }
38
+ function extractConstraint(id, node, objectMap) {
39
+ const typeChild = node.children.find((c) => c.name === "Type");
40
+ const typeName = (typeChild ? getPropertyValue(typeChild, 0) : undefined) ?? getPropertyValue(node, 2) ?? "";
41
+ const type = TYPE_NAMES[typeName] ?? "unknown";
42
+ const props = new Map();
43
+ for (const entry of getPropertyEntries(node)) {
44
+ props.set(entry.name, entry.values);
45
+ }
46
+ const bool3 = (prefix, fallback) => [
47
+ num(props.get(`${prefix}X`), fallback ? 1 : 0) !== 0,
48
+ num(props.get(`${prefix}Y`), fallback ? 1 : 0) !== 0,
49
+ num(props.get(`${prefix}Z`), fallback ? 1 : 0) !== 0,
50
+ ];
51
+ const constraint = {
52
+ id,
53
+ name: cleanFBXName(getPropertyValue(node, 1) ?? "Constraint"),
54
+ type,
55
+ typeName,
56
+ targets: [],
57
+ weight: num(props.get("Weight"), 100) / 100,
58
+ active: num(props.get("Active"), 1) !== 0,
59
+ affectTranslation: [true, true, true],
60
+ affectRotation: [true, true, true],
61
+ affectScale: [false, false, false],
62
+ offsetTranslation: [0, 0, 0],
63
+ offsetRotation: [0, 0, 0],
64
+ offsetScale: [1, 1, 1],
65
+ aimVector: vec3(props.get("AimVector"), [1, 0, 0]),
66
+ upVector: vec3(props.get("UpVector"), [0, 1, 0]),
67
+ worldUpVector: vec3(props.get("WorldUpVector"), [0, 1, 0]),
68
+ worldUpType: num(props.get("WorldUpType"), 0),
69
+ ikPoleVector: vec3(props.get("PoleVector"), [0, 0, 0]),
70
+ };
71
+ switch (type) {
72
+ case "aim":
73
+ constraint.affectRotation = bool3("Affect", true);
74
+ constraint.offsetRotation = vec3(props.get("RotationOffset"), [0, 0, 0]);
75
+ break;
76
+ case "parent":
77
+ constraint.affectTranslation = bool3("AffectTranslation", true);
78
+ constraint.affectRotation = bool3("AffectRotation", true);
79
+ constraint.affectScale = bool3("AffectScale", false);
80
+ break;
81
+ case "position":
82
+ constraint.affectTranslation = bool3("Affect", true);
83
+ constraint.offsetTranslation = vec3(props.get("Translation"), [0, 0, 0]);
84
+ break;
85
+ case "rotation":
86
+ constraint.affectRotation = bool3("Affect", true);
87
+ constraint.offsetRotation = vec3(props.get("Rotation"), [0, 0, 0]);
88
+ break;
89
+ case "scale":
90
+ constraint.affectScale = bool3("Affect", true);
91
+ constraint.offsetScale = vec3(props.get("Scaling"), [1, 1, 1]);
92
+ break;
93
+ default:
94
+ break;
95
+ }
96
+ // Connected objects: the child of each OP connection is the model, the property names its role.
97
+ const weightScale = type === "singleChainIK" ? 1 : 100;
98
+ for (const conn of objectMap.connections) {
99
+ if (conn.parentId !== id || conn.type !== "OP" || !conn.propertyName) {
100
+ continue;
101
+ }
102
+ const modelNode = objectMap.objects.get(conn.childId);
103
+ if (!modelNode || modelNode.name !== "Model") {
104
+ continue;
105
+ }
106
+ const role = conn.propertyName;
107
+ const targetName = cleanFBXName(getPropertyValue(modelNode, 1) ?? "");
108
+ switch (role) {
109
+ case "Constrained Object":
110
+ case "Constrained object (Child)":
111
+ constraint.nodeId = conn.childId;
112
+ break;
113
+ case "Source":
114
+ case "Source (Parent)":
115
+ case "Aim At Object":
116
+ case "Pole Vector Object":
117
+ constraint.targets.push({
118
+ modelId: conn.childId,
119
+ weight: num(props.get(`${targetName}.Weight`), weightScale) / weightScale,
120
+ offsetTranslation: vec3(props.get(`${targetName}.Offset T`), [0, 0, 0]),
121
+ offsetRotation: vec3(props.get(`${targetName}.Offset R`), [0, 0, 0]),
122
+ offsetScale: vec3(props.get(`${targetName}.Offset S`), [1, 1, 1]),
123
+ });
124
+ break;
125
+ case "World Up Object":
126
+ constraint.worldUpNodeId = conn.childId;
127
+ break;
128
+ case "First Joint":
129
+ constraint.ikFirstJointId = conn.childId;
130
+ break;
131
+ case "End Joint":
132
+ constraint.ikEndJointId = conn.childId;
133
+ break;
134
+ case "Effector":
135
+ constraint.ikEffectorId = conn.childId;
136
+ break;
137
+ default:
138
+ break;
139
+ }
140
+ }
141
+ return constraint;
142
+ }
143
+ //# sourceMappingURL=constraints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constraints.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/interpreter/constraints.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\n/**\n * FBX constraints (FbxConstraint): aim, parent, position, rotation, scale and single chain IK. The property and\n * connection conventions follow the FBX SDK (target weights are `<TargetName>.Weight`, parent offsets\n * `<TargetName>.Offset T/R/S`, the constrained node arrives through the \"Constrained Object\" connection).\n */\nimport { type FBXNode, getPropertyValue, cleanFBXName } from \"../types/fbxTypes\";\nimport { type FBXObjectMap } from \"./connections\";\nimport { getPropertyEntries } from \"./propertyTemplates\";\n\nexport type FBXConstraintType = \"aim\" | \"parent\" | \"position\" | \"rotation\" | \"scale\" | \"singleChainIK\" | \"unknown\";\n\nexport type Vec3 = [number, number, number];\nexport type Bool3 = [boolean, boolean, boolean];\n\n/** One weighted target of a constraint. */\nexport interface FBXConstraintTarget {\n /** Model id of the target node */\n modelId: number;\n /** Normalized weight (file value / 100, or as-is for IK pole targets) */\n weight: number;\n /** Parent constraint translation offset expressed in the target's space */\n offsetTranslation: Vec3;\n /** Parent constraint rotation offset in degrees, expressed in the target's space */\n offsetRotation: Vec3;\n /** Parent constraint scale offset expressed in the target's space */\n offsetScale: Vec3;\n}\n\n/** A constraint object of the file, with its targets and parameters resolved. */\nexport interface FBXConstraintData {\n /** Constraint object id */\n id: number;\n /** Constraint name */\n name: string;\n /** Resolved constraint kind */\n type: FBXConstraintType;\n /** Constraint type name as written in the file (e.g. \"Parent-Child\") */\n typeName: string;\n /** Constrained model */\n nodeId?: number;\n /** Weighted targets in file order */\n targets: FBXConstraintTarget[];\n /** Global weight (file value / 100) */\n weight: number;\n /** False when the constraint is switched off in the file */\n active: boolean;\n /** Which translation axes the constraint drives */\n affectTranslation: Bool3;\n /** Which rotation axes the constraint drives */\n affectRotation: Bool3;\n /** Which scale axes the constraint drives */\n affectScale: Bool3;\n /** Translation offset of the constrained node */\n offsetTranslation: Vec3;\n /** Rotation offset of the constrained node, in degrees */\n offsetRotation: Vec3;\n /** Scale offset of the constrained node */\n offsetScale: Vec3;\n /** Aim: local axis that points at the target */\n aimVector: Vec3;\n /** Aim: local axis aligned with the up direction */\n upVector: Vec3;\n /** Aim: world up direction (world up modes 2 and 3) */\n worldUpVector: Vec3;\n /** Aim: 0 scene up, 1 aim up node, 2 align to node, 3 vector, 4 none */\n worldUpType: number;\n /** Aim: model id of the world up object (world up modes 1 and 2) */\n worldUpNodeId?: number;\n /** Single chain IK: model id of the first joint of the chain */\n ikFirstJointId?: number;\n /** Single chain IK: model id of the last joint of the chain */\n ikEndJointId?: number;\n /** Single chain IK: model id of the effector */\n ikEffectorId?: number;\n /** Single chain IK: pole vector */\n ikPoleVector: Vec3;\n}\n\nconst TYPE_NAMES: Record<string, FBXConstraintType> = {\n Aim: \"aim\",\n \"Parent-Child\": \"parent\",\n \"Position From Positions\": \"position\",\n \"Rotation From Rotations\": \"rotation\",\n \"Scale From Scales\": \"scale\",\n \"Single Chain IK\": \"singleChainIK\",\n};\n\nfunction vec3(values: unknown[] | undefined, fallback: Vec3): Vec3 {\n if (values && typeof values[0] === \"number\" && typeof values[1] === \"number\" && typeof values[2] === \"number\") {\n return [values[0], values[1], values[2]];\n }\n return fallback;\n}\n\nfunction num(values: unknown[] | undefined, fallback: number): number {\n const v = values?.[0];\n return typeof v === \"number\" ? v : typeof v === \"boolean\" ? (v ? 1 : 0) : fallback;\n}\n\n/** Reads every constraint object of the scene. */\nexport function extractConstraints(objectMap: FBXObjectMap): FBXConstraintData[] {\n const constraints: FBXConstraintData[] = [];\n for (const [id, node] of Array.from(objectMap.objects)) {\n if (node.name !== \"Constraint\") {\n continue;\n }\n constraints.push(extractConstraint(id, node, objectMap));\n }\n return constraints;\n}\n\nfunction extractConstraint(id: number, node: FBXNode, objectMap: FBXObjectMap): FBXConstraintData {\n const typeChild = node.children.find((c) => c.name === \"Type\");\n const typeName = (typeChild ? getPropertyValue<string>(typeChild, 0) : undefined) ?? getPropertyValue<string>(node, 2) ?? \"\";\n const type = TYPE_NAMES[typeName] ?? \"unknown\";\n const props = new Map<string, unknown[]>();\n for (const entry of getPropertyEntries(node)) {\n props.set(entry.name, entry.values);\n }\n const bool3 = (prefix: string, fallback: boolean): Bool3 => [\n num(props.get(`${prefix}X`), fallback ? 1 : 0) !== 0,\n num(props.get(`${prefix}Y`), fallback ? 1 : 0) !== 0,\n num(props.get(`${prefix}Z`), fallback ? 1 : 0) !== 0,\n ];\n\n const constraint: FBXConstraintData = {\n id,\n name: cleanFBXName(getPropertyValue<string>(node, 1) ?? \"Constraint\"),\n type,\n typeName,\n targets: [],\n weight: num(props.get(\"Weight\"), 100) / 100,\n active: num(props.get(\"Active\"), 1) !== 0,\n affectTranslation: [true, true, true],\n affectRotation: [true, true, true],\n affectScale: [false, false, false],\n offsetTranslation: [0, 0, 0],\n offsetRotation: [0, 0, 0],\n offsetScale: [1, 1, 1],\n aimVector: vec3(props.get(\"AimVector\"), [1, 0, 0]),\n upVector: vec3(props.get(\"UpVector\"), [0, 1, 0]),\n worldUpVector: vec3(props.get(\"WorldUpVector\"), [0, 1, 0]),\n worldUpType: num(props.get(\"WorldUpType\"), 0),\n ikPoleVector: vec3(props.get(\"PoleVector\"), [0, 0, 0]),\n };\n\n switch (type) {\n case \"aim\":\n constraint.affectRotation = bool3(\"Affect\", true);\n constraint.offsetRotation = vec3(props.get(\"RotationOffset\"), [0, 0, 0]);\n break;\n case \"parent\":\n constraint.affectTranslation = bool3(\"AffectTranslation\", true);\n constraint.affectRotation = bool3(\"AffectRotation\", true);\n constraint.affectScale = bool3(\"AffectScale\", false);\n break;\n case \"position\":\n constraint.affectTranslation = bool3(\"Affect\", true);\n constraint.offsetTranslation = vec3(props.get(\"Translation\"), [0, 0, 0]);\n break;\n case \"rotation\":\n constraint.affectRotation = bool3(\"Affect\", true);\n constraint.offsetRotation = vec3(props.get(\"Rotation\"), [0, 0, 0]);\n break;\n case \"scale\":\n constraint.affectScale = bool3(\"Affect\", true);\n constraint.offsetScale = vec3(props.get(\"Scaling\"), [1, 1, 1]);\n break;\n default:\n break;\n }\n\n // Connected objects: the child of each OP connection is the model, the property names its role.\n const weightScale = type === \"singleChainIK\" ? 1 : 100;\n for (const conn of objectMap.connections) {\n if (conn.parentId !== id || conn.type !== \"OP\" || !conn.propertyName) {\n continue;\n }\n const modelNode = objectMap.objects.get(conn.childId);\n if (!modelNode || modelNode.name !== \"Model\") {\n continue;\n }\n const role = conn.propertyName;\n const targetName = cleanFBXName(getPropertyValue<string>(modelNode, 1) ?? \"\");\n switch (role) {\n case \"Constrained Object\":\n case \"Constrained object (Child)\":\n constraint.nodeId = conn.childId;\n break;\n case \"Source\":\n case \"Source (Parent)\":\n case \"Aim At Object\":\n case \"Pole Vector Object\":\n constraint.targets.push({\n modelId: conn.childId,\n weight: num(props.get(`${targetName}.Weight`), weightScale) / weightScale,\n offsetTranslation: vec3(props.get(`${targetName}.Offset T`), [0, 0, 0]),\n offsetRotation: vec3(props.get(`${targetName}.Offset R`), [0, 0, 0]),\n offsetScale: vec3(props.get(`${targetName}.Offset S`), [1, 1, 1]),\n });\n break;\n case \"World Up Object\":\n constraint.worldUpNodeId = conn.childId;\n break;\n case \"First Joint\":\n constraint.ikFirstJointId = conn.childId;\n break;\n case \"End Joint\":\n constraint.ikEndJointId = conn.childId;\n break;\n case \"Effector\":\n constraint.ikEffectorId = conn.childId;\n break;\n default:\n break;\n }\n }\n return constraint;\n}\n"]}
@@ -1,5 +1,8 @@
1
+ import { type FBXUserPropertyValue } from "./propertyTemplates.js";
1
2
  import { type FBXDocument } from "../types/fbxTypes.js";
2
3
  import { type FBXGeometryData } from "./geometry.js";
4
+ import { type FBXCurveGeometryData } from "./nurbs.js";
5
+ import { type FBXConstraintData } from "./constraints.js";
3
6
  import { type FBXMaterialData } from "./materials.js";
4
7
  import { type FBXSkinData } from "./skeleton.js";
5
8
  import { type FBXRigData } from "./rig.js";
@@ -11,8 +14,10 @@ export interface FBXModelData {
11
14
  id: number;
12
15
  name: string;
13
16
  subType: string;
14
- /** Geometry attached to this model (if it's a Mesh type) */
17
+ /** Geometry attached to this model (meshes and tessellated NURBS surfaces) */
15
18
  geometry?: FBXGeometryData;
19
+ /** Curve geometry attached to this model (Line and NurbsCurve) */
20
+ curve?: FBXCurveGeometryData;
16
21
  /** Materials assigned to this model */
17
22
  materials: FBXMaterialData[];
18
23
  /** Child models */
@@ -44,18 +49,68 @@ export interface FBXModelData {
44
49
  /** Whether backface culling is disabled ("CullingOff") */
45
50
  cullingOff: boolean;
46
51
  /** User-defined custom properties from Properties70 */
47
- customProperties?: Record<string, string | number | boolean>;
52
+ customProperties?: Record<string, FBXUserPropertyValue>;
53
+ /** LOD group settings when this model is a LodGroup; children are the levels in order */
54
+ lodGroup?: FBXLodGroupData;
55
+ /** Display layer (CollectionExclusive) the model belongs to */
56
+ displayLayer?: FBXDisplayLayerData;
48
57
  /** Recoverable model import diagnostics */
49
58
  diagnostics: string[];
50
59
  }
60
+ /** LOD group settings (NodeAttribute "LodGroup") */
61
+ export interface FBXLodGroupData {
62
+ /** Switch distance for level i+1 (level 0 has none). In scene units, or percent of screen when `relative`. */
63
+ thresholds: number[];
64
+ /** ThresholdsUsedAsPercentage */
65
+ relative: boolean;
66
+ /** DisplayLevels|LevelN: 0 use LOD, 1 show, 2 hide */
67
+ displayLevels: number[];
68
+ }
69
+ /** Display layer (CollectionExclusive "DisplayLayer") */
70
+ export interface FBXDisplayLayerData {
71
+ id: number;
72
+ name: string;
73
+ show: boolean;
74
+ freeze: boolean;
75
+ color: [number, number, number];
76
+ modelIds: number[];
77
+ }
78
+ /** One member of a selection set: a model, optionally with a component selection on its mesh */
79
+ export interface FBXSelectionNodeData {
80
+ modelId: number;
81
+ /** IsTheNodeInSet: the whole node is selected (as opposed to only components) */
82
+ includeNode: boolean;
83
+ /** Selected control point indices (VertexIndexArray) */
84
+ vertices?: number[];
85
+ /** Selected edge indices (EdgeIndexArray) */
86
+ edges?: number[];
87
+ /** Selected polygon indices (PolygonIndexArray) */
88
+ faces?: number[];
89
+ }
90
+ /** Selection set (Collection "SelectionSet") */
91
+ export interface FBXSelectionSetData {
92
+ id: number;
93
+ name: string;
94
+ members: FBXSelectionNodeData[];
95
+ }
51
96
  /** Camera data extracted from FBX */
52
97
  export interface FBXCameraData {
53
98
  /** Model ID this camera is attached to */
54
99
  modelId: number;
100
+ /** NodeAttribute object ID (animation curves target this) */
101
+ attributeId: number;
55
102
  /** Camera name */
56
103
  name: string;
57
- /** Field of view in degrees */
104
+ /** Vertical field of view in degrees */
58
105
  fieldOfView: number;
106
+ /** Horizontal field of view in degrees */
107
+ fieldOfViewX: number;
108
+ /** ApertureMode: 0 horizontal and vertical, 1 horizontal, 2 vertical, 3 focal length */
109
+ apertureMode: number;
110
+ /** Aperture (film gate after gate fit) size in inches */
111
+ apertureSizeInch: [number, number];
112
+ /** Orthographic view size (width, height) in scene units */
113
+ orthographicSize: [number, number];
59
114
  /** Near clip plane */
60
115
  nearPlane: number;
61
116
  /** Far clip plane */
@@ -74,6 +129,8 @@ export interface FBXCameraData {
74
129
  orthoZoom?: number;
75
130
  /** Camera roll in degrees when present */
76
131
  roll?: number;
132
+ /** User-defined properties on the camera attribute */
133
+ userProperties?: Record<string, FBXUserPropertyValue>;
77
134
  /** Known unsupported or unrecognized camera properties */
78
135
  unknownProperties: string[];
79
136
  /** Recoverable camera import diagnostics */
@@ -83,6 +140,8 @@ export interface FBXCameraData {
83
140
  export interface FBXLightData {
84
141
  /** Model ID this light is attached to */
85
142
  modelId: number;
143
+ /** NodeAttribute object ID (animation curves target this) */
144
+ attributeId: number;
86
145
  /** Light name */
87
146
  name: string;
88
147
  /** Light type: 0=Point, 1=Directional, 2=Spot */
@@ -107,6 +166,15 @@ export interface FBXLightData {
107
166
  enableFarAttenuation?: boolean;
108
167
  /** Whether the source light requested shadow casting */
109
168
  castShadows?: boolean;
169
+ /** Near/far attenuation ranges in scene units (when enabled) */
170
+ nearAttenuationStart?: number;
171
+ nearAttenuationEnd?: number;
172
+ farAttenuationStart?: number;
173
+ farAttenuationEnd?: number;
174
+ /** Area light shape: 0 rectangle, 1 sphere */
175
+ areaLightShape?: number;
176
+ /** User-defined properties on the light attribute */
177
+ userProperties?: Record<string, FBXUserPropertyValue>;
110
178
  /** Known unsupported or unrecognized light properties */
111
179
  unknownProperties: string[];
112
180
  /** Recoverable light import diagnostics */
@@ -118,6 +186,8 @@ export interface FBXSceneData {
118
186
  rootModels: FBXModelData[];
119
187
  /** All geometries in the scene */
120
188
  geometries: FBXGeometryData[];
189
+ /** All curve geometries (lines and tessellated NURBS curves) */
190
+ curves: FBXCurveGeometryData[];
121
191
  /** All materials in the scene */
122
192
  materials: FBXMaterialData[];
123
193
  /** Skin deformers (skeletons + vertex weights) */
@@ -134,6 +204,12 @@ export interface FBXSceneData {
134
204
  lights: FBXLightData[];
135
205
  /** Scene-level unsupported feature diagnostics */
136
206
  diagnostics: FBXSceneDiagnostic[];
207
+ /** Constraints (aim, parent, position, rotation, scale, IK) */
208
+ constraints: FBXConstraintData[];
209
+ /** Display layers */
210
+ displayLayers: FBXDisplayLayerData[];
211
+ /** Selection sets */
212
+ selectionSets: FBXSelectionSetData[];
137
213
  /** Global settings */
138
214
  upAxis: number;
139
215
  upAxisSign: number;
@@ -142,8 +218,17 @@ export interface FBXSceneData {
142
218
  coordAxis: number;
143
219
  coordAxisSign: number;
144
220
  unitScaleFactor: number;
221
+ /** Scene frame rate derived from GlobalSettings TimeMode / CustomFrameRate */
222
+ frameRate: number;
145
223
  }
146
224
  /**
147
225
  * Interpret a parsed FBX document into scene data.
148
226
  */
149
- export declare function interpretFBX(doc: FBXDocument): FBXSceneData;
227
+ /** Options controlling how the document is interpreted. */
228
+ export interface FBXInterpretOptions {
229
+ /** Segments per knot span when tessellating NURBS surfaces; defaults to the Step stored in the file */
230
+ nurbsSubdivision?: number;
231
+ /** Shift every clip so its first key sits at time 0 (default true); false keeps the authored times */
232
+ rebaseKeyframes?: boolean;
233
+ }
234
+ export declare function interpretFBX(doc: FBXDocument, options?: FBXInterpretOptions): FBXSceneData;