import { type FBXDocument } from "../types/fbxTypes.js"; import { type FBXObjectMap } from "./connections.js"; import { type FBXCurveData, type FBXLayerBlend } from "./animationCurve.js"; export { FBX_TIME_UNIT } from "./animationCurve.js"; export type { FBXCurveData, FBXExtrapolation, FBXExtrapolationMode, FBXInterpolationType, FBXKeyframe, FBXLayerBlend } from "./animationCurve.js"; export { combineLayerValue, evaluateCurve, eulerToQuat, quatToEuler } from "./animationCurve.js"; /** An animation curve node (T/R/S for one bone) */ export interface FBXCurveNodeData { /** Property type: "T" (translation), "R" (rotation), "S" (scale) */ type: string; /** Target model (bone) ID */ targetModelId: number; /** Curves for each axis */ curves: FBXCurveData[]; /** Index of the owning layer within the stack's layer list */ layerIndex: number; /** Default channel values (`d|X`, `d|Y`, `d|Z`) used for channels without a curve */ defaultValues?: [number, number, number]; } /** Non-transform animation curve node (property animation), evaluated by the loader when a Babylon mapping exists. */ export interface FBXUnsupportedCurveNodeData { /** Raw AnimationCurveNode property type/name */ type: string; /** CurveNode object ID */ id: number; /** Index of the owning layer within the stack's layer list */ layerIndex: number; /** Target object ID if the curve node is connected to an object/property */ targetId: number | null; /** OP connection property name on the target, e.g. Visibility */ propertyName?: string; /** Number of connected animation curves that were ignored */ curveCount: number; /** Connected curves preserved for diagnostics and future runtime support */ curves: FBXCurveData[]; /** Local default values stored on the unsupported curve node */ defaultValues: Record; } /** Recoverable animation import issue. */ export interface FBXAnimationDiagnostic { /** Diagnostic category. */ type: "multiple-animation-layers" | "unsupported-layer-blend-mode" | "partial-layer-weight" | "unsupported-curve-node"; /** Human-readable diagnostic message. */ message: string; /** Animation layer name associated with the diagnostic, if applicable. */ layerName?: string; /** AnimationCurveNode object ID associated with the diagnostic, if applicable. */ curveNodeId?: number; /** AnimationCurveNode type/name associated with the diagnostic, if applicable. */ curveNodeType?: string; /** Target object ID associated with the diagnostic, if applicable. */ targetId?: number | null; /** Target property name associated with the diagnostic, if applicable. */ propertyName?: string; } /** Animation layer with blend mode info */ export interface FBXAnimationLayerData { /** Layer name */ name: string; /** Layer weight (0-100, default 100) */ weight: number; /** Layer weight normalized to 0-1 */ normalizedWeight: number; /** Blend mode: 0=Additive, 1=Override, 2=OverridePassthrough */ blendMode: number; /** Resolved blend semantics used by the evaluator */ blend: FBXLayerBlend; /** Animated layer weight (0-100), when the Weight property carries a curve */ weightCurve?: FBXCurveData; /** Curve nodes in this layer */ curveNodes: FBXCurveNodeData[]; /** Unsupported/non-TRS curve nodes preserved for diagnostics */ unsupportedCurveNodes: FBXUnsupportedCurveNodeData[]; /** Recoverable layer diagnostics */ diagnostics: FBXAnimationDiagnostic[]; } /** Options for animation extraction. */ export interface FBXAnimationExtractOptions { /** * Shift each clip so its first key sits at time 0 (default true). False keeps the times authored in the file, so * clips of one file stay aligned with each other and with the declared stack range. */ rebaseKeyframes?: boolean; } /** One animation clip (AnimationStack) */ export interface FBXAnimationStackData { /** Animation name */ name: string; /** Clip start in seconds after any keyframe rebasing */ startTime: number; /** Clip stop in seconds after any keyframe rebasing */ stopTime: number; /** Duration in seconds */ duration: number; /** Per-bone curve nodes (flattened from all layers for backward compat) */ curveNodes: FBXCurveNodeData[]; /** Animation layers (preserves blend mode info) */ layers: FBXAnimationLayerData[]; /** Unsupported/non-TRS curve nodes preserved for diagnostics */ unsupportedCurveNodes: FBXUnsupportedCurveNodeData[]; /** Recoverable animation diagnostics */ diagnostics: FBXAnimationDiagnostic[]; } /** * Extract all animation stacks from the FBX scene. */ export declare function extractAnimations(objectMap: FBXObjectMap, doc?: FBXDocument, options?: FBXAnimationExtractOptions): FBXAnimationStackData[]; /** * Samples an FBX animation curve at a specific time. * @param curveData - Curve data to sample * @param time - Time in seconds * @returns The sampled value, or null when the curve has no keys */ export declare function sampleFBXCurveAtTime(curveData: FBXCurveData | undefined, time: number): number | null; /** * Pre-7000 files store animation in a top-level `Takes` block instead of AnimationStack/Layer/CurveNode objects: * * Takes: { Take: "name" { LocalTime: start, stop * Model: "Model::joint1" { Channel: "Transform" { Channel: "T" { Channel: "X" { Default, KeyVer, KeyCount, Key } } } } } } * * Each take becomes one animation stack with a single layer. Models are matched through the same legacy string ids * that the connection resolver synthesizes for 6.x objects. */ export declare function extractLegacyTakes(doc: FBXDocument, objectMap: FBXObjectMap, rebaseKeyframes?: boolean): FBXAnimationStackData[]; /** * Evaluates one transform channel (T, R or S) of a target at `time`, blending every animation layer of the stack the * way the FBX SDK does: the first layer animating the channel replaces the static value, later layers are combined * according to their blend mode, weight and accumulation modes. * @param curveNodes - Curve nodes targeting this model (any layers, any types) * @param layers - Stack layers, in order * @param type - Channel to evaluate * @param staticValue - Value when nothing animates the channel * @param rotationOrder - Rotation order of the target (for rotation composition) * @param time - Time in seconds */ export declare function evaluateLayeredChannel(curveNodes: readonly FBXCurveNodeData[], layers: readonly FBXAnimationLayerData[], type: "T" | "R" | "S", staticValue: readonly [number, number, number], rotationOrder: number, time: number): [number, number, number]; /** Curves of one animated property (or blend shape weight) contributed by one animation layer. */ export interface FBXLayeredPropertySource { /** Index of the owning layer within the stack's layer list */ layerIndex: number; /** Curves of the property, keyed by channel name (`d|X`, `d|DeformPercent`, ...) */ curves: readonly FBXCurveData[]; /** Default channel values stored on the curve node */ defaultValues?: Record; } /** * Evaluates an animated property through the animation layers: the base layer replaces the static value, every * further layer blends onto the running result according to its blend mode and (possibly animated) weight, like * `evaluateLayeredChannel` does for transforms. * @param sources - Per-layer curves of the property * @param layers - Stack layers, in order * @param channels - Channel names to evaluate, in output order * @param staticValue - Value per channel when nothing animates it * @param time - Time in seconds * @returns One value per channel */ export declare function evaluateLayeredProperty(sources: readonly FBXLayeredPropertySource[], layers: readonly FBXAnimationLayerData[], channels: readonly string[], staticValue: readonly number[], time: number): number[]; /** * True when every curve of the given channel is inside a constant (stepped) segment at `time`, so a baked key at * that time should hold its value instead of interpolating towards the next sample. */ export declare function isChannelSteppedAt(curveNodes: readonly FBXCurveNodeData[], type: "T" | "R" | "S", time: number): boolean;