/** * @file StateMachine.ts * @description Finite State Machine System with Graphical Editor Support * PRO-1.4: Professional Editor Features * * Features: * - Hierarchical state machines (HSM) * - Transitions with conditions and actions * - Entry/Exit/Update callbacks * - Transition triggers and events * - Visual editor integration * - Debugging and history * - Parallel states * - Animation state machine support */ import type { EntityId, Vec2 } from '../core/types'; export type SMStateType = 'normal' | 'entry' | 'exit' | 'any' | 'parallel' | 'submachine'; export interface SMParameter { name: string; type: 'bool' | 'int' | 'float' | 'trigger'; value: boolean | number; } export type SMConditionOperator = 'equals' | 'notEquals' | 'greater' | 'less' | 'greaterEqual' | 'lessEqual'; export interface SMCondition { id: string; parameter: string; operator: SMConditionOperator; value: boolean | number; } export interface SMConditionGroup { id: string; /** AND = all must pass, OR = any must pass */ mode: 'and' | 'or'; conditions: SMCondition[]; } export interface SMTransition { id: string; name?: string; /** Source state ID (or 'any' for any-state transitions) */ from: string; /** Target state ID */ to: string; /** Conditions that must be met */ conditions: SMConditionGroup[]; /** Transition duration (for blending) */ duration: number; /** Priority (lower = higher priority) */ priority: number; /** Can interrupt current state */ canInterrupt: boolean; /** Trigger name (consumed on use) */ trigger?: string; /** Offset into target state (0-1) for animation */ targetOffset?: number; /** Custom transition curve */ curve?: 'linear' | 'easeIn' | 'easeOut' | 'easeInOut'; /** Editor: control points for curved transition line */ controlPoints?: Vec2[]; /** Is this transition muted (disabled) */ muted?: boolean; } export interface SMState { id: string; name: string; type: SMStateType; /** Position in editor */ position: Vec2; /** Size in editor (for comments) */ size?: Vec2; /** Custom color */ color?: string; /** State speed multiplier (for animation) */ speed: number; /** Motion/animation clip reference */ motion?: string; /** Is this the default state? */ isDefault?: boolean; /** Sub-state machine ID (for submachine states) */ submachineId?: string; /** Child states (for parallel/hierarchical) */ children?: string[]; /** Tags for grouping */ tags?: string[]; /** Custom data */ customData?: Record; /** Behaviors attached to this state */ behaviors?: SMStateBehavior[]; } export interface SMStateBehavior { id: string; type: string; enabled: boolean; properties: Record; } export interface SMLayer { id: string; name: string; /** Layer weight (for animation blending) */ weight: number; /** Blending mode */ blendMode: 'override' | 'additive'; /** Sync with another layer */ syncedLayer?: string; /** Is this layer active? */ active: boolean; /** States in this layer */ states: SMState[]; /** Transitions in this layer */ transitions: SMTransition[]; /** Default state ID */ defaultState?: string; /** Any-state transitions */ anyStateTransitions: SMTransition[]; } export interface SMDefinition { id: string; name: string; description?: string; /** Parameters */ parameters: SMParameter[]; /** Layers */ layers: SMLayer[]; /** Metadata */ metadata?: { author?: string; version?: string; created?: number; modified?: number; }; } export interface SMContext { entityId: EntityId; dt: number; time: number; world: unknown; /** Custom services */ services: Map; } export interface SMStateInstance { stateId: string; layerId: string; enterTime: number; elapsedTime: number; normalizedTime: number; isTransitioning: boolean; } export interface SMTransitionInstance { transitionId: string; fromState: string; toState: string; startTime: number; duration: number; progress: number; } export type SMEventType = 'state-enter' | 'state-exit' | 'state-update' | 'transition-start' | 'transition-complete' | 'parameter-changed'; export interface SMEvent { type: SMEventType; timestamp: number; layerId: string; data: unknown; } export type SMCallback = (context: SMContext, state: SMState) => void; export type SMTransitionCallback = (context: SMContext, transition: SMTransition) => void; export declare class StateMachine { private definition; private layerStates; private activeTransitions; private parameters; private triggers; /** Callbacks */ private onEnter; private onExit; private onUpdate; private onTransitionStart; private onTransitionComplete; /** Event listeners */ private eventListeners; /** Debugging */ private history; private historyLimit; debugMode: boolean; constructor(definition: SMDefinition); private initializeParameters; private initializeLayers; setParameter(name: string, value: boolean | number): void; getParameter(name: string): boolean | number | undefined; setBool(name: string, value: boolean): void; getBool(name: string): boolean; setFloat(name: string, value: number): void; getFloat(name: string): number; setInteger(name: string, value: number): void; getInteger(name: string): number; setTrigger(name: string): void; resetTrigger(name: string): void; update(context: SMContext): void; private updateLayer; private findValidTransition; private evaluateConditions; private evaluateConditionGroup; private evaluateCondition; private startTransition; private completeTransition; private callOnEnter; private callOnExit; private callOnUpdate; registerOnEnter(stateId: string, callback: SMCallback): void; registerOnExit(stateId: string, callback: SMCallback): void; registerOnUpdate(stateId: string, callback: SMCallback): void; registerOnTransitionStart(callback: SMTransitionCallback): void; registerOnTransitionComplete(callback: SMTransitionCallback): void; on(event: SMEventType, listener: (event: SMEvent) => void): void; off(event: SMEventType, listener: (event: SMEvent) => void): void; private emit; getCurrentState(layerId?: string): SMState | null; getCurrentStateId(layerId?: string): string | null; isInState(stateId: string, layerId?: string): boolean; isTransitioning(layerId?: string): boolean; getTransitionProgress(layerId?: string): number; getStateTime(layerId?: string): number; forceState(stateId: string, layerId?: string): void; reset(): void; getHistory(): SMEvent[]; clearHistory(): void; getDebugInfo(): { layers: Array<{ id: string; name: string; currentState: string | null; isTransitioning: boolean; transitionProgress: number; }>; parameters: Record; }; getDefinition(): SMDefinition; clone(): StateMachine; } /** Extended state machine for animation control */ export declare class AnimatorController extends StateMachine { private motionValues; private blendTrees; constructor(definition: SMDefinition); /** Get blended motion value for animation sampling */ getMotionValue(layerId: string): number; /** Get current motion/clip name */ getMotionClip(layerId?: string): string | null; /** Register a blend tree for a state */ registerBlendTree(stateId: string, blendTree: BlendTree): void; /** Sample blend tree for current parameters */ sampleBlendTree(stateId: string): BlendTreeSample | null; private getParameterMap; } export type BlendTreeType = '1d' | '2d-simple' | '2d-freeform' | 'direct'; export interface BlendTreeMotion { clip: string; position: number | Vec2; speed?: number; mirror?: boolean; threshold?: number; } export interface BlendTreeSample { clips: Array<{ clip: string; weight: number; speed: number; mirror: boolean; }>; } export declare class BlendTree { type: BlendTreeType; parameterX: string; parameterY?: string; motions: BlendTreeMotion[]; constructor(type: BlendTreeType, parameterX: string, parameterY?: string); addMotion(motion: BlendTreeMotion): void; sample(parameters: Record): BlendTreeSample; private sample1D; private sample2D; private sampleDirect; } export declare function createStateMachine(definition: SMDefinition): StateMachine; export declare function createAnimatorController(definition: SMDefinition): AnimatorController; export declare function createBlendTree1D(parameter: string): BlendTree; export declare function createBlendTree2D(parameterX: string, parameterY: string, type?: '2d-simple' | '2d-freeform'): BlendTree; export declare function createSMDefinition(name: string): SMDefinition; export declare function createSMLayer(name: string): SMLayer; export declare function createSMState(name: string, type?: SMStateType): SMState; export declare function createSMTransition(from: string, to: string): SMTransition; export declare function createSMParameter(name: string, type: SMParameter['type'], value?: boolean | number): SMParameter; export declare function createSMCondition(parameter: string, operator: SMConditionOperator, value: boolean | number): SMCondition; export declare function createSMConditionGroup(mode?: 'and' | 'or'): SMConditionGroup; export declare function createSMContext(params: { entityId: EntityId; dt: number; time: number; world: unknown; }): SMContext;