📄 functionsequence.as
字号:
package flare.animate
{
import flare.util.Arrays;
import flare.util.Maths;
/**
* Transition that runs sub-transitions in sequential order while also
* invoking a function before each sub-transition is run. Each function
* must take a Transition instance (often a Transitioner) as input.
* Function sequences can only be played forwards; any attempt to play
* one in reverse will result in an error.
*
* <p>Function sequences are useful for ensuring a particular function
* is run before a sub-transition begins. For example, the function may
* populate the values of a Transitioner on the fly, or may be used to
* control other variables or side-effects that affect the subsequent
* sub-transition(s).</p>
*/
public class FunctionSequence extends Sequence
{
/** @private */
protected var _funcs:/*Function*/Array = [];
/** @private */
protected var _offsetStart:Boolean = true;
/** Flag indicating if extra time should be added to the transition to
* offset the running time of invoked functions. True by default. */
public function get offsetStartTime():Boolean { return _offsetStart; }
public function set offsetStartTime(b:Boolean):void { _offsetStart = b; }
// --------------------------------------------------------------------
/**
* Creates a new FunctionSequence transition.
*/
public function FunctionSequence()
{
super();
}
/**
* Adds a function call and corresponding transition to this sequence.
* As the sequence plays, functions will be called at the beginning of
* their subsequence, with the provided transition passed as the
* function's sole argument.
* @param f a function to call at the beginning of a sub-sequence
* @param t the transition to run after the function call. This
* transition will be passed in as an input to the function. This
* value should be either a <code>Transition</code> instance or
* a number indicating the duration for a new
* <code>Transitioner</code>.
*/
public function push(f:Function, t:*):void
{
var tr:Transition = t is Transition ? Transition(t)
: Transitioner.instance(t);
super.add(tr);
_funcs.push(f);
}
/**
* Removes a sub-transition function from this sequence. The
* corresponding transition instance will also be removed.
* @param t the transition to remove
* @return true if the transition was found and removed, false
* otherwise
*/
public function removeFunction(f:Function):Boolean
{
if (running) throw new Error("Transition is running!");
var idx:int = Arrays.remove(_funcs, f);
var rem:Boolean = idx > 0;
if (rem) {
_trans.splice(idx, 1);
_dirty = true;
}
return rem;
}
/** @inheritDoc */
public override function add(t:Transition):void
{
super.add(t);
_funcs.push(null);
}
/**
* Removes a sub-transition from this sequence. Any corresponding
* function will also be removed.
* @param t the transition to remove
* @return true if the transition was found and removed, false
* otherwise
*/
public override function remove(t:Transition):Boolean
{
if (running) throw new Error("Transition is running!");
var idx:int = Arrays.remove(_trans, t);
var rem:Boolean = idx > 0;
if (rem) {
_funcs.splice(idx, 1);
_dirty = true;
}
return rem;
}
/** @inheritDoc */
public override function dispose():void {
super.dispose();
Arrays.clear(_funcs);
}
/**
* Plays this function sequence. Function sequences can not be played
* in reverse.
* @param reverse If true, an error will be thrown and the sequence
* will not play.
*/
public override function play(reverse:Boolean=false):void {
if (reverse) throw new Error(
"Function sequences can't be played in reverse.");
super.play(false);
}
private function invoke(idx:int, t:Transition):void {
var f:Function = _funcs[idx];
if (f != null) {
if (_offsetStart) {
var d:Number = new Date().time;
f(t);
d = new Date().time - d;
_start += d;
} else {
f(t);
}
}
}
// --------------------------------------------------------------------
/**
* Sets up each sub-transition.
*/
protected override function setup():void
{
}
/**
* Starts this sequence transition, starting the first sub-transition
* to be played.
*/
protected override function start():void
{
if (_trans.length > 0) {
var t:Transition = _trans[_idx];
invoke(_idx, t); t.doSetup(); t.doStart(false);
}
}
/**
* Steps this sequence transition, ensuring that any sub-transitions
* between the previous and current progress fraction are properly
* invoked.
* @param ef the current progress fraction.
*/
internal override function step(ef:Number):void
{
// find the right sub-transition
var t:Transition, f0:Number, f1:Number, i:int, inc:int;
f0 = _fracs[_idx]; f1 = _fracs[_idx+1]; inc = (ef<=f0 ? -1 : 1);
for (i = _idx; i>=0 && i<_trans.length; i+=inc) {
// get transition and progress fractions
t = _trans[i]; f0 = _fracs[i]; f1 = _fracs[i+1];
// hand-off to new transition
if (i != _idx) {
invoke(i, t); t.doSetup(); t.doStart(false);
}
if ((inc<0 && ef >= f0) || (inc>0 && ef <= f1)) break;
t.doStep(inc<0 ? 0 : 1);
t.doEnd();
}
_idx = i; // set the transition index
if (_idx >= 0 && _idx < _trans.length) {
// run transition with mapped fraction
t.doStep(Maths.invLinearInterp(ef, f0, f1));
}
}
} // end of class FunctionSequence
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -