package alternativa.engine3d.animation { import alternativa.engine3d.alternativa3d; /** * Cостояние проигрывания анимации в контроллере. */ public final class AnimationState { use namespace alternativa3d; /** * Проигрываемая анимация. */ public var animation:Animation; /** * Зацикленность анимации. Зацикленная анимация будет проигрываться сначала после достижения конца. */ public var loop:Boolean; /** * Для незацикленной анимации задает время с отсчетом от конца анимации после которого начнется затухание анимации. * 0 - без затухания, 1 - затухание с начала анимации. */ public var endingFadeOut:Number = 0; private var fadeInTime:Number; private var fadedIn:Boolean; private var fadeInPosition:Number; private var fadeOutTime:Number; private var fadedOut:Boolean; private var fadeOutPosition:Number; private var manualControl:Boolean = false; private var _controller:AnimationController; private var _name:String; private var _played:Boolean = false; private var _position:Number = 0; /** * Конструктор состояния анимации, вызывается в AnimationController. * * @see AnimationController */ public function AnimationState(controller:AnimationController, animation:Animation, name:String, loop:Boolean) { this.animation = animation; this._controller = controller; this._name = name; this.loop = loop; } /** * Проиграть анимацию сначала. * * @param fade время в течение которого вес анимации должен увеличиться с нуля до максимального значения. */ public function replay(fade:Number = 0):void { if (!_played) { play(fade); _position = 0; } } /** * Продолжить проигрывание анимации с текущей позиции. * * @param fade время в течение которого вес анимации должен увеличиться с нуля до максимального значения. */ public function play(fade:Number = 0):void { if (!_played) { _played = true; fadeInTime = fade; fadedIn = true; if (fadedOut) { fadeInPosition = fadeInTime*(1 - fadeOutPosition/fadeOutTime); fadedOut = false; } else { fadeInPosition = 0; } manualControl = false; } } /** * Остановить проигрывание анимации. * * @param fade время в течение которого вес анимации должен уменьшиться с максимального значения до 0. */ public function stop(fade:Number = 0):void { if (_played) { _played = false; fadeOutTime = fade; if (fadedIn) { fadeOutPosition = fadeOutTime*(1 - fadeInPosition/fadeInTime); fadedIn = false; fadedOut = true; } else { if (!fadedOut) { fadeOutPosition = 0; fadedOut = true; } } manualControl = false; } } /** * @private */ alternativa3d function prepareBlending():void { if (animation != null) { animation.prepareBlending(); } } private function loopPosition():void { if (_position < 0) { // _position = (length <= 0) ? 0 : _position % length; _position = 0; } else { if (_position >= animation.length) { _position = (animation.length <= 0) ? 0 : _position % animation.length; } } } private function fading(position:Number):Number { if (position > 1) { return 1; } if (position < 0) { return 0; } return position; } /** * @private */ alternativa3d function update(interval:Number):void { if (animation == null) { return; } var weight:Number = animation.weight; if (_played) { _position += interval*animation.speed; if (loop) { loopPosition(); if (fadedIn) { fadeInPosition += interval; if (fadeInPosition < fadeInTime) { weight *= fading(fadeInPosition/fadeInTime); } else { fadedIn = false; } } } else { if (_position < 0) { _position = 0; if (interval < 0) { _played = false; } weight = 0; } else { if (_position > animation.length) { if (interval > 0) { _position = 0; _played = false; } else { _position = animation.length; } weight = 0; } else { if ((_position/animation.length + endingFadeOut) > 1) { fadedOut = true; fadeOutTime = endingFadeOut; fadeOutPosition = _position/animation.length + endingFadeOut - 1; } else { fadedOut = false; } if (fadedIn) { fadeInPosition += interval; } if ((fadedIn && (fadeInPosition < fadeInTime)) && fadedOut) { var w1:Number = fading(fadeInPosition/fadeInTime); var w2:Number = fading(1 - fadeOutPosition/fadeOutTime); if (w1 < w2) { weight *= w1; } else { weight *= w2; fadedIn = false; } } else { if (fadedIn) { if (fadeInPosition < fadeInTime) { weight *= fading(fadeInPosition/fadeInTime); } else { fadedIn = false; } } else if (fadedOut) { weight *= fading(1 - fadeOutPosition/fadeOutTime); } } } } } } else { if (!manualControl) { if (fadedOut) { _position += interval*animation.speed; if (loop) { loopPosition(); } else { if (_position < 0) { _position = 0; } else { if (_position >= animation.length) { _position = animation.length; } } } fadeOutPosition += interval; if (fadeOutPosition < fadeOutTime) { weight *= fading(1 - fadeOutPosition/fadeOutTime); } else { fadedOut = false; weight = 0; } } else { weight = 0; } } } if (weight != 0) { animation.blend(_position, weight); } } /** * Контроллер, управляющий воспроизведением анимации. */ public function get controller():AnimationController { return _controller; } /** * Имя анимации в контроллере. */ public function get name():String { return _name; } /** * Проигрывается анимация в данный момент или нет. */ public function get played():Boolean { return _played; } /** * Позиция проигрывания анимации. */ public function get position():Number { return _position; } /** * @private */ public function set position(value:Number):void { _position = value; manualControl = true; _played = false; fadedIn = false; fadedOut = false; } } }