import com.mosesSupposes.fuse.FuseKitCommon; /** * The Fuse Kit [beta1.1z3] * Copyright (c) 2006 Moses Gunesch, MosesSupposes.com * * Distributed under MIT Open Source License, see Fuse-Kit-License.html (in fuse package directory) * Easing Equations (c) 2003 Robert Penner used by permission, see PennerEasing * Visit http://www.mosessupposes.com/Fuse * * @ignore * * Pass this class to {@link com.mosesSupposes.fuse.ZigoEngine#register} or {@link com.mosesSupposes.fuse.ZigoEngine#simpleSetup} to enable Fuse-style Object Syntax parsing capability with {@link com.mosesSupposes.fuse.ZigoEngine#doTween}. Note that registering Fuse is not required to use this feature. * @usage *
ZigoEngine.doTween({ target:clip1, scale:200, ease:Strong.easeIn, time:"00:50", startAt:"01:50" });*
ZigoEngine.doTween
. These otherwise untracked instances are given an ID of -1 and are auto-deleted by the actionscript_video_com_mosesSupposes_fuse_FuseItem class upon completion using removeInstance
.
*/
private static var _aInstances:Array;
/**
* This method needn't be called as method call is rerouted here automatically upon ZigoEngine.doTween
.
* @return comma-delimited string listing properties successfully added to the engine.
*/
public static function doTween():String
{
for (var i:String in arguments) {
if (typeof arguments[i]=='object') {
if (_aInstances==undefined) _aInstances = new Array();
var o:actionscript_video_com_mosesSupposes_fuse_FuseItem = new actionscript_video_com_mosesSupposes_fuse_FuseItem(_aInstances.length, arguments[i], -1);
return o.startItem();
}
}
}
// --------------------------------------------------------------------//
// 1. Fuse-access methods
// 2. Constructor & parseProfile
// 3. doTweens, tween event handlers, utils
// --------------------------------------------------------------------//
// 1.
/**
* @exclude
* label property queried by Fuse
* @return label string if actionscript_video_com_mosesSupposes_fuse_FuseItem contains a label property
*/
public function getLabel():String
{
return _oElements.label;
}
/**
* @exclude
* Fuse needs to retrieve original objects passed for Array methods that return them
* @return true if trigger has been fired within currently playing item
*/
public function hasTriggerFired():Boolean
{
return (_bTrigger==true);
}
/**
* @exclude
* Fuse needs to retrieve original objects passed for Array methods that return them
* @return original action object as passed by user
*/
public function getInitObj():Object
{
return (_initObj);
}
/**
* @exclude
* Fuse calls this to get additional playing or paused targets to add to defaults when getActiveTargets is called on a Fuse.
* @return a list of target objects or empty array
*/
public function getActiveTargets(targetList:Array):Array
{
if (!(_aTweens.length>0)) return targetList;
var found:Boolean = false;
for (var i:String in _aTweens) {
// filter duplicates
for (var j:String in targetList) {
if (targetList[j]==(_aTweens[i]).targ) {
found = true;
break;
}
}
if (found==false) {
targetList.unshift((_aTweens[i]).targ);
}
}
return targetList;
}
/**
* @exclude
*/
public function toString():String { return String((_sID())+':'+_sImage); }
/**
* @exclude
* Called by parent Fuse to retrieve simple freestanding delays (note that in certain cases actionscript_video_com_mosesSupposes_fuse_FuseItems use ZigoEngine tweens to time complex delays, such as those that appear within an action group). Such non-tweened delays are centralized into the parent Fuse, which runs a setInterval timer and handles pause/resume behavior for that delay.
* @param scope current default scope set in parent Fuse instance
* @return delay in seconds
*/
public function evalDelay(scope:Object):Number
{
var d:Object = _oElements.delay;
if (d instanceof Function) {
d = d.apply((_oElements.delayscope!=undefined) ? _oElements.delayscope : scope);
}
if (typeof d=='string') d = (parseClock(String(d)));
if (_global.isNaN(Number(d))==true) return 0;
return Number(d);
}
/**
* @exclude
* Called by parent Fuse to play the actionscript_video_com_mosesSupposes_fuse_FuseItem, including triggering commands, firing callbacks not associated with tweens, and starting tweens.
* @param targs - an array of default targets currently set in parent Fuse instance
* @param scope - current default scope set in parent Fuse instance
* @return returns successfully tweened props for doTween()
*/
public function startItem(targs:Array, scope:Object):String
{
_ZigoEngine = _global.com.mosesSupposes.fuse.ZigoEngine;
var fuse:Object = _global.com.mosesSupposes.fuse.Fuse;
var outputLevel:Number = (fuse!=undefined) ? fuse.OUTPUT_LEVEL : _ZigoEngine.OUTPUT_LEVEL;
// Fuse command like 'pause' or 'stop'. v2.0: Only delay,scope,args are retained for items containing command.
if (_oElements.command!=null) {
var validCommands:String = '|start|stop|pause|resume|skipTo|setStartProps|';
var cs:Object = (_oElements.scope || scope); // profile scope used for eval only. command always sent to parent fuse
var command:String = (_oElements.command instanceof Function) ? String(_oElements.command.apply(cs)) : String(_oElements.command); // user can pass a Delegate to scope this
// IMPORTANT: args param is not used during eval, args are passed to Fuse, primarily for use with skipTo(index/label)
var args:Array = (_oElements.args instanceof Function) ? _oElements.args.apply(cs) : _oElements.args;
if (validCommands.indexOf('|'+command+'|')==-1 || (command=='skipTo' && args==undefined)) {
if (outputLevel>0) FuseKitCommon.error('111', command);
}
else {
_nPlaying = 1;
if (!(args instanceof Array)) args = (args==null) ? [] : [args];
dispatchRequest(String(command), args);
}
return null;
}
// Changed order to deal with skipLevel. Now we tween first then fire callbacks and events.
if (_aTweens.length>0) this.stop();
_ZigoEngine.addListener(this); // For monitoring targets that go missing. Only one corresponding remove, in stop(), which is called by complete().
_nPlaying = 2; // Special flag meaning doTweens is running, important for avoiding onTweenInterrupt/End conflicts.
var propsAdded:String = null;
if (_aProfiles.length>0) {
if (_ZigoEngine==undefined) {
FuseKitCommon.error('112');
}
else {
propsAdded = doTweens(targs, scope, false);
}
}
// do not move. Callbacks can contain pause or other play commands, so this is checked afterward
_nPlaying = 1;
// Non-tween callbacks & events (skipped if skipLevel is 2 and all tweens failed)
var fa:Array = _oElements.aEvents;
for (var i:String in fa) {
if (propsAdded==null && _aTweens.length>0 && (fa[i]).skipLevel==2) continue;
fireEvents(fa[i],scope,outputLevel);
}
if (propsAdded==null && !(_aTweens.length>0) && _nPlaying==1) {
if (outputLevel==3) FuseKitCommon.output('-'+(_sID())+' no tweens added - item done. [getTimer()='+getTimer()+']');
complete();
}
return propsAdded;
}
/**
* @exclude
* Called by parent Fuse to stop the actionscript_video_com_mosesSupposes_fuse_FuseItem's tweens. If currently playing, the internal method onStop is called which clears current tween list and associated listeners.
*/
public function stop():Void
{
// (for onTweenInterrupt)
var doOnStop:Boolean = (_nPlaying>-1);
_nPlaying = -1;
// active stop: clear this item's tweens and remove listeners
if (doOnStop==true) onStop();
_ZigoEngine.removeListener(this);
}
// -- private --
/**
* @exclude
*/
private static function removeInstance(id:Number):Void
{
actionscript_video_com_mosesSupposes_fuse_FuseItem(_aInstances[id]).destroy();
delete _aInstances[id];
}
/**
* @exclude
* Clears active elements. (Fuse event reverse-subscribed by parent Fuse)
*/
private function onStop():Void
{
_bStartSet = false;
for (var i:String in _aTweens) {
var to:Object = _aTweens[i];
to.targ.removeListener(this);
_ZigoEngine.removeTween(to.targ, to.props);
delete _aTweens[i];
}
delete _aTweens;
_bTrigger = false;
}
/**
* @exclude
* An event dispatched by parent Fuse to all child actionscript_video_com_mosesSupposes_fuse_FuseItems to preset tween start-values.
* @param o event object containing a .filter property which can specify exclusion from the call
*/
private function evtSetStart(o:Object):Void
{
// no starts to set or Fuse is about to play this item.
if (_sImage.indexOf('StartProps:')==-1 || o.curIndex==_nItemID) {
return;
}
if (o.all!=true) {
var match:Boolean = false;
for (var i:String in o.filter) {
if (Number(o.filter[i])==_nItemID || String(o.filter[i])==_oElements.label) match = true;
}
if (match==false) {
return;
}
}
doTweens(o.targs, o.scope, true);
// flag removed when parent Fuse stopped.
_bStartSet = true;
}
/**
* @exclude
* Called by parent Fuse to pause or resume the actionscript_video_com_mosesSupposes_fuse_FuseItem's tweens and tweened delays. During resume it is not assumed that targets and pauses are intact, each is checked and the internal tween array is trimmed if items have gone missing.
* @param resume indicates whether it is a pause or resume call
*/
public function pause(resume:Boolean):Void
{
if (_nPlaying==-1) return;
_nPlaying = ((resume==true) ? 1 : 0);
for (var i:String in _aTweens) {
var o:Object = _aTweens[i];
var t:Object = o.targ;
var p:Object = o.props;
if (resume==true) {
// Is pause intact? Target/prop could have been manipulated since it was paused here.
var missing:Array = [];
var oldTL:Number = _aTweens.length;
for (var j:String in p) {
if (_ZigoEngine.isTweenPaused(t,p[j])==false) missing.push(p[j]);
}
if (missing.length>0) {
onTweenEnd({__zigoID__:o.targZID, props:missing, isResume:true});
}
if (_aTweens.length==oldTL) { // otherwise onTweenEnd removed the tween
t.addListener(this);
_ZigoEngine.unpauseTween(t, o.props);
}
}
else {
t.removeListener(this);
_ZigoEngine.pauseTween(t, o.props);
}
}
if (resume==true && !(_aTweens.length>0)) { // no tweens.
complete();
}
else if (resume==true) {
_ZigoEngine.addListener(this);
}
else {
_ZigoEngine.removeListener(this);
}
}
/**
* @exclude
* Called by parent Fuse to clear actionscript_video_com_mosesSupposes_fuse_FuseItem instance's memory and listeners during Fuse's destroy cycle.
*/
public function destroy():Void
{
var doRemove:Boolean = (_nPlaying>-1);
_nPlaying = -1;
for (var i:String in _aTweens) {
var o:Object = _aTweens[i];
o.targ.removeListener(this);
if (doRemove==true) _ZigoEngine.removeTween(o.targ, o.props);
delete _aTweens[i];
}
for (var j:String in this) {
delete this[j];
}
}
/**
* @exclude
*/
private function dispatchRequest(type:String, args:Array):Void
{// avoids import of Fuse class since actionscript_video_com_mosesSupposes_fuse_FuseItem can be used with ZigoEngine as an Object Syntax extension
var f:Object = _global.com.mosesSupposes.fuse.Fuse.getInstance(_nFuseID);
if (!(args instanceof Array) && args!=null) args = (new Array(args));
Function(f[type]).apply(f, args);
}
// 2.
/**
* @exclude
* Concise string ID representing the parent Fuse's fixed ID and the actionscript_video_com_mosesSupposes_fuse_FuseItem's current index in the Fuse, such as "Fuse#0>Item#0"
*/
private function _sID():String // like "Fuse#0>Item#0"
{
var str:String;
if (_nFuseID==-1) {
str = 'One-off tween ';
}
else {
var fuse:Object = _global.com.mosesSupposes.fuse.Fuse.getInstance(_nFuseID);
str = 'Fuse#'+String(_nFuseID);
if (fuse.label!=undefined) str+=':"'+fuse.label+'"';
}
str+='>Item#'+String(_nItemID);
if (_oElements.label!=undefined) str+=':"'+_oElements.label+'"';
return str;
}
/**
* @exclude
* Constructor - Attempts to parse action(s) into _oElements
and _aProfiles
, building the verbose string ID _sImage
in the process.
* @param id current index of actionscript_video_com_mosesSupposes_fuse_FuseItem in parent Fuse instance
* @param o action object or Array of action objects pushed into the Fuse for parsing
* @param fuseID permanent unique ID of parent Fuse stored in _nFuseID
*/
public function actionscript_video_com_mosesSupposes_fuse_FuseItem (id:Number, o:Object, fuseID:Number)
{
_ZigoEngine = _global.com.mosesSupposes.fuse.ZigoEngine;
this._nItemID = id;
this._nFuseID = fuseID;
this._initObj = o;
_aProfiles = [];
_oElements = { aEvents:[] };
_oTemps = {};
if (!(o instanceof Array)) o = [o];
var fuse:Object = _global.com.mosesSupposes.fuse.Fuse;
_oTemps.outputLevel = (fuse!=undefined) ? fuse.OUTPUT_LEVEL : _global.com.mosesSupposes.fuse.ZigoEngine.OUTPUT_LEVEL;
// v2 Command actions can only contain delay, label, scope, args and may not be nested in groups.
if (o.length==1) {
var o0:Object = o[0];
var obj:Object = (o0.action!=undefined) ? o0.action : o0;
if (obj.__buildMode!=true && obj.command!=undefined) {
_oElements.command = obj.command;
_oElements.scope = obj.scope; // v2.0: changed commandscope & commandargs to scope, args.
_oElements.args = obj.args;
_sImage = ' Elements:['+('command'+((typeof obj.command=='string') ? ':"'+obj.command+'", ' : ', '));
if (obj.label!=undefined && typeof obj.label=='string') {
_sImage+=('label:"'+obj.label+'", ');
_oElements.label = obj.label; // one label per Command Action
}
if (obj.delay!=undefined) {
_sImage+='delay, ';
_oElements.delay = obj.delay; // one delay per Command Action
}
if (obj.func!=undefined && _oTemps.outputLevel>0) FuseKitCommon.error('113');
return;
}
}
// persistant vars for looping through actions
_oTemps.sImgS = '';
_oTemps.sImgE = '';
_oTemps.sImgB = '';
_oTemps.afl = 0;
_oTemps.ael = 0;
_oTemps.twDelayFlag = false;
_oTemps.nActions = o.length;
_oTemps.fuseProps = FuseKitCommon._fuseprops();
_oTemps.cbProps = FuseKitCommon._cbprops();
_oTemps.sUP = FuseKitCommon._underscoreable();
_oTemps.sCT = FuseKitCommon._cts();
_oTemps.bTriggerFound = false;
// Parse each profile.
for (var i:String in o) {
var item:Object = o[i];
if (item.label!=undefined && typeof item.label=='string') _oElements.label = item.label; // one string-only label per actionscript_video_com_mosesSupposes_fuse_FuseItem
var a:Object;
var aap:Object;
var bApplied:Boolean = Boolean(typeof item.action=='object' && !(item.action instanceof Array)); // reject arrays in action param!
if (bApplied==true) {
a = item.action;
aap = { // applied-action profile, these props are mixed into the action during parseProfile.
delay:item.delay,
target:item.target,
addTarget:item.addTarget,
label:item.label,
trigger:item.trigger
};
}
else {
a = item;
}
var oPr:Object = parseProfile(a, aap);
if (oPr!=undefined) {
_aProfiles.unshift(oPr);
}
}
// build string image (if a command was passed in, this happens up top.)
_sImage = '';
var str:String = '';
if (_oElements.label!=undefined) str+=('label:"'+_oElements.label+'", ');
if (_oTemps.afl>0) str+= ((_oTemps.afl>1) ? _oTemps.afl+' callbacks, ' : 'callback, ');
if (_oElements.delay!=undefined || _oTemps.twDelayFlag==true) str+='delay, ';
if (_oTemps.bTriggerFound==true) str+='trigger, ';
if (_oTemps.ael>0) str+= ((_oTemps.ael>1) ? _oTemps.ael+' events, ' : 'event, ');
if (str!='') _sImage+=' Elements:['+(str.slice(0,-2))+']';
if (_oTemps.sImgS!='') _sImage+= ' StartProps:['+(_oTemps.sImgS.slice(0,-2))+']'; // careful: "StartProps:" is checked in evtSetStart
if (_oTemps.sImgE!='') _sImage+= ' Props:['+(_oTemps.sImgE.slice(0,-2))+']';
if (_oTemps.sImgB!='') _sImage+= ' Simple Syntax Props:['+(_oTemps.sImgB.slice(0,-1))+']';
delete _oTemps;
}
/**
* @exclude
* Used by constructor to parse each action object passed (multiple objects can be passed in an Array for simultaneous action groups). The parsing process is a fairly complex procudure that blocks tween start & end properties, tags 'auto-fill' end properties in which only a start value was passed, extracts freestanding items that do not require tweens, and generates proxy tweens used to handle delays within groups.
* @param obj the action object to be parsed into a profile and pushed into _aProfiles
* @param aap Stands for 'applied action profile' object. When an 'applied action' is encountered, this override profile mixes properties into the resulting profile.
* @return parsed profile object
*/
private function parseProfile(obj:Object, aap:Object):Object
{
var i:String, j:String, k:String;
// Build Mode (simple syntax) objects
if (obj.__buildMode==true) {
if (obj.command!=undefined) {
if (obj.command=='delay') { // addCommand('delay',Number)
_oElements.delay = obj.commandargs;
}
else {
_oElements.command = obj.command;
_oElements.args = obj.commandargs;
}
}
if (obj.func!=undefined) {
_oTemps.afl++;
_oElements.aEvents.unshift({f:obj.func,s:obj.scope,a:obj.args});
}
if (obj.tweenargs!=undefined) {
_oTemps.sImgB += (obj.tweenargs[1].toString()+','); // (allowing duplicates in simple syntax props image to save code, since it could be comma-delim str)
return obj;
}
return null;
}
var oPr:Object = {
delay:(aap.delay!=undefined) ? aap.delay : obj.delay,
ease:obj.ease,
seconds:obj.seconds,
event:obj.event,
eventparams:obj.eventparams,
skipLevel:(typeof obj.skipLevel=='number' && obj.skipLevel>=0 && obj.skipLevel<=2) ? obj.skipLevel : _ZigoEngine.SKIP_LEVEL, // correct early for use in actionscript_video_com_mosesSupposes_fuse_FuseItem.doTweens
oSP:{},
oEP:{},
oAFV:{}
};
// trigger
var trigger:Object = ((aap.trigger!=undefined) ? aap.trigger : obj.trigger); // can be true or number, not parsed until doTweens
if (trigger!=undefined) {
if (_oTemps.bTriggerFound==false) { // only one trigger is allowed per actionscript_video_com_mosesSupposes_fuse_FuseItem
oPr.trigger = trigger;
_oTemps.bTriggerFound = true;
}
else if (_oTemps.outputLevel>0) {
FuseKitCommon.error('126',(_sID()),trigger);
}
}
// synonyms
if (oPr.delay==undefined) oPr.delay = obj.startAt;
if (oPr.ease==undefined) oPr.ease = obj.easing; // synonym (cannot use OR eval with string for some reason)
if (oPr.seconds==undefined) oPr.seconds = ((obj.duration!=undefined) ? obj.duration : obj.time); // synonym (cannot use OR eval with string for some reason)
// applied action target param overrides action target param
if (aap.target!=undefined) oPr.target = ((aap.target instanceof Array) ? aap.target : [aap.target]);
else if (obj.target!=undefined) oPr.target = ((obj.target instanceof Array) ? obj.target : [obj.target]);
// applied action addTarget param adds to action addTarget param (don't change order)
if (obj.addTarget!=undefined) oPr.addTarget = ((obj.addTarget instanceof Array) ? obj.addTarget : [obj.addTarget]);
if (aap.addTarget!=undefined) {
if (oPr.addTarget==undefined) oPr.addTarget = ((aap.addTarget instanceof Array) ? aap.addTarget : [aap.addTarget]);
else oPr.addTarget = ((oPr.addTarget instanceof Array) ? (oPr.addTarget.concat(aap.addTarget)) : ((new Array(oPr.addTarget)).concat(aap.addTarget)));
}
var bTwFlag:Boolean = false;
for (j in obj) {
var v:Object = obj[j];
if ((_oTemps.cbProps).indexOf('|'+j+'|')>-1) {//'|cycles|easyfunc|func|scope|args|startfunc|startscope|startargs|updfunc|updscope|updargs|extra1|extra2|'
if (j!='skipLevel') oPr[j] = v;
continue;
}
if ((_oTemps.fuseProps).indexOf('|'+j+'|')>-1) {//'|command|label|delay|event|eventparams|target|addTarget|trigger|startAt|ease|easing|seconds|duration|time|'
if (j=='command' && _oTemps.nActions>1 && _oTemps.outputLevel>0) FuseKitCommon.error('114',String(v));
continue;
}
if (typeof v=='object') {
var copy:Object = (v instanceof Array) ? ([]) : {};
for (k in v) copy[k] = v[k];
v = copy;
}
var se:Object;
var seCP:Object;
if (j.indexOf('start')==0) {
j = j.slice(6);
se = oPr.oSP;
}
else {
se = oPr.oEP;
}
if (ADD_UNDERSCORES==true && _oTemps.sUP.indexOf('|_'+j+'|')>-1) j='_'+j;
if (_oTemps.sCT.indexOf('|'+j+'|')>-1) {
var addPct:Boolean = (j=='_tintPercent' && se.colorProp.p=='_tint');
var addTint:Boolean = (j=='_tint' && se.colorProp.p=='_tintPercent');
if (se.colorProp==undefined || addPct==true || addTint==true) { // write only 1 color prop per profile, saves cleanup work during tween.
if (addPct==true) se.colorProp = {p:'_tint', v:{ tint:se.colorProp.v, percent:v }};
else if (addTint==true) se.colorProp = {p:'_tint', v:{ tint:v, percent:se.colorProp.v }};
else se.colorProp = {p:j, v:v};
bTwFlag = true;
}
else if (_oTemps.outputLevel>0) {
FuseKitCommon.error('115',(_sID()),j);
}
}
else if (v!=null) { // (null values are only accepted for color props)
if (se==oPr.oEP && (obj.controlX!=undefined || obj.controlY!=undefined) && (j.indexOf('control')==0 || j=='_x' || j=='_y')) { // group bezier end props
if (se._bezier_==undefined) se._bezier_ = {};
if (j.indexOf('control')==0) se._bezier_[j] = v; //controlX, controlY
else (se._bezier_[(j.charAt(1))] = v); // x, y
}
else {
se[j] = v;
}
bTwFlag = true;
}
} // end parse props(j), still looping through actions(i)
/* Special "Nontween delay" cases
* (Note that normally delays are played by parent fuse except in these cases)
* -start/update callbacks without any tween props
* -delay within multi-item group
*/
if (bTwFlag==false && (oPr.trigger!=undefined ||
((oPr.delay!=undefined || oPr.seconds!=undefined) &&
( (oPr.startfunc!=undefined || oPr.updfunc!=undefined)
|| (oPr.func!=undefined && _oTemps.nActions>1) )))) {
if (_ZigoEngine==undefined) { // ignore output level for crucial error message
FuseKitCommon.error('116');
}
else {
if (oPr.func!=undefined) _oTemps.afl++;
if (oPr.event!=undefined) _oTemps.ael++;
oPr._doTimer = true;
if (oPr.delay!=undefined) _oTemps.twDelayFlag = true;
return oPr;
}
}
if (bTwFlag==true) { // do a final round of cleanup on tween profile and build string image
var bEC:Boolean = (oPr.oEP.colorProp!=undefined);
for (var l:Number=0; l<2; l++) {
var se:Object = (l==0) ? oPr.oSP : oPr.oEP;
var str:String = (l==0) ? _oTemps.sImgS : _oTemps.sImgE;
var sCP:String = se.colorProp.p;
if (sCP!=undefined) { // combine color back in (colorProp was used to enforce single start/end color)
se[sCP] = se.colorProp.v;
delete se.colorProp;
}
if ((se._xscale!=undefined || se._scale!=undefined) && (se._width!=undefined || se._size!=undefined)) {
var discard:String = (se._xscale!=undefined) ? '_xscale' : '_scale';
delete se[discard];
if (_oTemps.outputLevel>0) FuseKitCommon.error('115',(_sID()),discard);
}
if ((se._yscale!=undefined || se._scale!=undefined) && (se._height!=undefined || se._size!=undefined)) {
var discard:String = (se._yscale!=undefined) ? '_yscale' : '_scale';
delete se[discard];
if (_oTemps.outputLevel>0) FuseKitCommon.error('115',(_sID()),discard);
}
for (j in se) {
if (str.indexOf(j+', ')==-1) str+=(j+', ');
if (se==oPr.oSP) {
if (oPr.oEP[j]==undefined && !(j==sCP && bEC==true)) { // add 'autofill' lookup
oPr.oAFV[j] = true;
oPr.oEP[j] = [];
}
}
}
((l==0) ? _oTemps.sImgS = str : _oTemps.sImgE = str);
}
return oPr;
}
// If no tweens were added or start/end profiles ended up empty, move usable props to _oElements
if (oPr.delay!=undefined && _oTemps.nActions==1) { // single-item actions only, see first if() in this block for multi-item actions
_oElements.delay = oPr.delay;
_oElements.delayscope = oPr.scope; // (internal, not a valid user prop!)
}
if (oPr.event!=undefined) {
_oTemps.ael++;
_oElements.aEvents.unshift({e:oPr.event, s:oPr.scope, ep:oPr.eventparams, skipLevel:oPr.skipLevel});
}
// actions containing startfunc/updfunc are handled w/nonTweenDelay.
var oldL:Number = _oElements.aEvents.length;
if (oPr.easyfunc!=undefined) _oElements.aEvents.push({cb:oPr.easyfunc, s:oPr.scope, skipLevel:oPr.skipLevel});
if (oPr.func!=undefined) _oElements.aEvents.push({f:oPr.func, s:oPr.scope, a:oPr.args, skipLevel:oPr.skipLevel});
_oTemps.afl+=(_oElements.aEvents.length-oldL);
delete oPr;
return undefined;
}
// 3.
/**
* @exclude
* Internal method to preset start values and generate tween calls to be sent to the engine. This is a complex procedure mainly due to the 'runtime-evaluation' feature of the Kit - scope, target(s), and all start and end values delegated to a function are retrieved by executing such functions just as the item is encountered in the sequence. doTweens handles all of this, builds and sends the tween calls while storing a reference in the internal _aTweens array. It then does emergency cleanup in situations where no tweens successfully fired and boolean end-values, callbacks, or delays are orphaned. Presetting start values is handled with 0-second tween calls which is important for interrupting any current tweens, which are monitored by any running Fuses; Start values with missing end-values are 'auto-filled' during doTweens.
* @param targs parent Fuse instance's current default targets
* @param defaultScope parent Fuse instance's current default scope
* @param setStart flag indicating that the doTweens call should only preset start values.
* @return returns successfully tweened props for doTween()
*/
private function doTweens(targs:Array, defaultScope:Object, setStart:Boolean):String
{
if (_aTweens==null) {
this._aTweens = [];
}
var fuse:Object = _global.com.mosesSupposes.fuse.Fuse;
var outputLevel:Number = (fuse!=undefined) ? fuse.OUTPUT_LEVEL : _ZigoEngine.OUTPUT_LEVEL;
var propsAdded:String = '';
var nTgErrors:Number = 0;
var i:String, j:String, k:String;
// Build-Mode actionscript_video_com_mosesSupposes_fuse_FuseItem (startprops option doesn't exist here)----------
if ((_aProfiles[0]).__buildMode==true) {
for (var h:Number=0; h<_aProfiles.length; h++) {
var twArgs:Array = (_aProfiles[h]).tweenargs;
if ((twArgs[6]).cycles===0 || ((twArgs[6]).cycles.toUpperCase())=='LOOP') {
delete (twArgs[6]).cycles;
if (outputLevel>0) FuseKitCommon.error('117',(_sID()));
}
var sProps:String = (_ZigoEngine.doTween.apply(_ZigoEngine, twArgs));
var aProps:Array = ((sProps==null) ? [] : (sProps).split(','));
if (aProps.length>0) {
_aTweens.push({targ:(twArgs[0]), props:aProps, targZID:(twArgs[0]).__zigoID__});
(twArgs[0]).addListener(this);
for (j in aProps) if (propsAdded.indexOf(aProps[j]+',')==-1) propsAdded+=(aProps[j]+',');
}
if (outputLevel==3) FuseKitCommon.output('\n-'+(_sID())+' TWEEN (simple syntax)\n\ttargets:['+twArgs[0]+']\n\tprops sent:['+twArgs[1]+']');
}
return ((propsAdded=='') ? null : propsAdded.slice(0,-1));
}
// Normal setStart, tweens ---------------------------------------------
var doSetStarts:Boolean = (_bStartSet!=true && (setStart==true || _sImage.indexOf('StartProps:')>-1));
// cycling through each action profile
for (var h:Number=0; h<_aProfiles.length; h++)
{
var pr:Object = _aProfiles[h];
// Set scope for callbacks + runtime-eval funcs.
// Each action may define a "scope" param which overrides Fuse default scope
var scope:Object = defaultScope; // this local is used many times within this loop for runtime-eval
if (pr.scope!=undefined) {
// scope param can be a runtime func (or delegate) that uses Fuse default scope to eval.
// (The evaled scope will cascade to updscope & startscope if they are funcs.)
scope = (pr.scope instanceof Function) ? pr.scope.apply(scope) : pr.scope;
}
// build event object
var event:Object;
if (pr.event!=undefined) {
var evt:String = ((pr.event instanceof Function) ? pr.event.apply(scope) : pr.event);
var evtparams:Object = ((pr.eventparams instanceof Function) ? pr.eventparams.apply(scope) : pr.eventparams);
if (evt!=undefined && evt.length>0) {
event = {e:evt, ep:evtparams, s:scope};
}
}
// build callback object
var skipLevel:Boolean = ((pr.skipLevel instanceof Function) ? pr.skipLevel.apply(scope) : pr.skipLevel);
var oSimpleCB:Object = { skipLevel:skipLevel };
var oCB:Object = { skipLevel:skipLevel };
if (pr.cycles!=undefined) {
var cycles:Object = ((pr.cycles instanceof Function) ? pr.cycles.apply(scope) : pr.cycles);
if ((Number(cycles)==0 || (String(cycles).toUpperCase())=='LOOP') && fuse!=undefined) {
delete pr.cycles;
if (outputLevel>0) FuseKitCommon.error('117',(_sID())); // infinite cycles not allowed in fuses
}
else {
oSimpleCB.cycles = oCB.cycles = cycles;
}
}
var cbstr:String='';
if (pr.easyfunc!=undefined || pr.func!=undefined || pr.startfunc!=undefined || pr.updfunc!=undefined) {
for (i in pr) {
if (i.indexOf('func')>-1) {
oCB[i] = pr[i];
}
else if (i=='startscope' || i=='updscope' || i.indexOf('args')>-1) {
oCB[i] = (pr[i] instanceof Function) ? Function(pr[i]).apply(scope) : pr[i];
}
}
if (scope!=undefined) {
if (oCB.func!=undefined && oCB.scope==undefined) oCB.scope = scope; // auto-fill callback scopes where possible
if (oCB.updfunc!=undefined && oCB.updscope==undefined) oCB.updscope = scope;
if (oCB.startfunc!=undefined && oCB.startscope==undefined) oCB.startscope = scope;
}
}
for (j in oCB) cbstr+=(j+':'+oCB[j]+'|');
// trigger: may be boolean, number, or runtime-eval function
var triggerTrue:Boolean = (pr.trigger===true);
var triggerTime:Number = undefined;
if (triggerTrue==false && pr.trigger!=undefined) {
triggerTime = ((pr.trigger instanceof Function) ? pr.trigger.apply(scope) : pr.trigger);
if (typeof triggerTime=='string') {
triggerTime = ((String(triggerTime).charAt(0)=='-') ? -(parseClock(String(triggerTime).slice(1))) : (parseClock(String(triggerTime))));
}
if (_global.isNaN(triggerTime)==true) triggerTime = undefined;
}
// Targets
// evaluated targets + addTargets
var targets:Array = [];
var aBase:Array = (pr.target==undefined) ? targs : pr.target;
var aTemp:Array = [];
var bTgError:Boolean = false;
// (any runtime func (or delegate) may return one targ or an array of targs)
for (i in aBase) {
var v:Object = aBase[i];
aTemp = aTemp.concat((v instanceof Function) ? v.apply(scope) : v);
}
for (i in pr.addTarget) {
var v:Object = pr.addTarget[i];
aTemp = aTemp.concat((v instanceof Function) ? v.apply(scope) : v);
}
for (i in aTemp) {
var v:Object = aTemp[i];
if (v!=null) {
var exists:Boolean = false;
for (j in targets) {
if (targets[j]==v) {
exists = true;
break;
}
}
if (exists==false) targets.unshift(v);
}
else {
bTgError = true;
}
}
var noTargError:Boolean = (targets.length==0 && pr._doTimer!=true);
var doTimer:Boolean = (pr._doTimer==true && targets.length==0);
if (bTgError==true || noTargError==true) {
nTgErrors++;
if (noTargError==true) {
continue;
}
}
// -- 1. start props --
if (doSetStarts==true)
{
// generate one ZigoEngine.doTween() call per target. Props parsed for runtime-eval, bools, validation
for (i in targets) {
var targ:Object = targets[i];
var aSP:Array = [];
var aSV:Array = [];
if (setStart==true) {
for (var q:String in pr.oEP) {
// Use 3rd param createNew to pre-create any missing filters on setStartProps, so the filter doesn't suddenly appear just before that action starts.
_global.com.mosesSupposes.fuse.FuseFMP.getFilterProp(targ,q,true);
}
}
for (var p:String in pr.oSP) {
var v:Object = pr.oSP[p];
if (v instanceof Function) v = v.apply(scope);
if (v===true || v===false) { // set start booleans immediately.
targ[p] = v;
if (pr.oAFV[p]==true) { // prohibit autofill with booleans.
for (k in pr.oEP[p]) if (pr.oEP[p][k].targ==targ) pr.oEP[p].splice(Number(k),1);
pr.oEP[p].push({targ:targ,val:'IGNORE'});
}
continue;
}
// autofill missing end values. Assume resets for known properties, otherwise take a snapshot of the current value to return to.
if (pr.oAFV[p]==true && !(p=='_colorReset' && v==100) && !(p=='_tintPercent' && v==0)) {// if no endprop was passed for startprop, store current value (does not apply to color prop which resets, preset during constructor parse)
var afv:Object;
if (p=='_tint' || p=='_colorTransform') {
afv = _ZigoEngine.getColorTransObj();
}
else if (('|_alpha|_contrast|_invertColor|_tintPercent|_xscale|_yscale|_scale|').indexOf('|'+p+'|')>-1) {
afv = 100;
}
else if (('|_brightness|_brightOffset|_colorReset|_rotation|').indexOf('|'+p+'|')>-1) {
afv = 0;
}
else { // snapshot current val, retaining target (which is important in the case of relative endvals)
var fmpVal:Number = _global.com.mosesSupposes.fuse.FuseFMP.getFilterProp(targ,p,true);
if (fmpVal!=null) afv = fmpVal;
else afv = (_global.isNaN(targ[p])==false) ? targ[p] : 0;
}
for (k in pr.oEP[p]) if (pr.oEP[p][k].targ==targ) pr.oEP[p].splice(Number(k),1);
pr.oEP[p].push({targ:targ,val:afv});
}
if (typeof v=='object') {
var copy:Object = (v instanceof Array) ? ([]) : {};
for (k in v) copy[k] = ((v[k]) instanceof Function) ? Function(v[k]).apply(scope) : v[k];
v = copy;
}
aSP.push(p);
aSV.push(v);
}// end startprops loop(n)
// set starts using egine, which monitors/broadcasts interrupts + parses complex properties.
if (aSV.length>0) {
if (outputLevel==3) FuseKitCommon.output('-'+(_sID())+' '+targ+' SET STARTS: '+['['+aSP+']', '['+aSV+']']);
_ZigoEngine.doTween(targ, aSP, aSV, 0);
}
} // end set starts
}// end if startprops
if (setStart==true) {
continue;
}
// -- 2. end props --
// Generate one ZigoEngine.doTween() call per target since envals can differ due to auto-fill feature.
// the last round of evaluating seconds, delay, and booleans is saved for the pickup round that happens after this loop
var seconds:Number;
var delay:Number;
var booleans:Object;// Group end-booleans per target to be set in onTweenEnd
var tweenSuccess:Boolean = false;
var targsOrProxy:Array = ((doTimer==false) ? targets : [0]);// force loop to occur once for targetless timer tweens
for (i in targsOrProxy) {
// Eval other per-profile params (putting this in the loop is less efficient but it allows runtime-eval-funcs to be run per target.)
// Q: when a user builds an action and there are multiple targets, do they want getters to be fired per target, or per action?
var ease:Object = pr.ease;
if (ease instanceof Function) { // could be a runtime eval function!
var ef:Function = (Function(ease));
if (typeof ef(1,1,1,1)!='number') ease = ef.apply(scope); // it's not a valid easing equation the engine can use.
}
seconds = (pr.seconds instanceof Function) ? pr.seconds.apply(scope) : pr.seconds;
if (seconds!=undefined) {
if (typeof seconds=='string') seconds = (parseClock(String(seconds)));
if (_global.isNaN(seconds)==true) seconds = (_ZigoEngine.DURATION || 0);
}
delay = (pr.delay instanceof Function) ? pr.delay.apply(scope) : pr.delay;
if (typeof delay=='string') delay = (parseClock(String(delay)));
if (delay==null || _global.isNaN(delay)==true) delay = 0;
if (doTimer==true) continue;
// ---------------------------------------------------------------
//parse
var targ:Object = targsOrProxy[i];
var aEP:Array = [];
var aEV:Array = [];
var numBools:Number = 0;
for (var p:String in pr.oEP) {
var v:Object = pr.oEP[p];
if (v instanceof Function) {
v = v.apply(scope);
}
if (v===true || v===false) { // end booleans will be attached to a tween & set in onTweenEnd.
if (booleans==undefined) booleans = {};
booleans[p] = v;
numBools++;
continue;
}
if (typeof v=='object') {
if ((v[0]).targ!=undefined) { // this is an autofilled property - match targets.
for (k in v) {
if ((v[k]).targ==targ) {
v = (v[k]).val;
break;
}
}
}
else {
var copy:Object = (v instanceof Array) ? ([]) : {};
for (k in v) copy[k] = ((v[k]) instanceof Function) ? Function(v[k]).apply(scope) : v[k];
v = copy;
}
}
if (v!='IGNORE') {
aEP.push(p);
aEV.push(v);
}
} // end endprops loop(n)
// normal tweens. monitor only the props that are added to the engine's tweenlist.
var aProps:Array = [];
if (aEV.length>0) {
// Only add callbacks/booleans/events in the case of single target - otherwise these things will be picked up with a fake tween later.
var sProps:String = _ZigoEngine.doTween(targ, aEP, aEV, seconds, ease, delay, oCB);
if (sProps!=null) aProps = (sProps.split(','));
if (aProps.length>0) {
var to:Object = {targ:targ, props:aProps, bools:booleans, targZID:targ.__zigoID__};
if (tweenSuccess==false) {
// Important: callback, event, trigger:true need to only be added once per profile.
oCB = oSimpleCB;
to.event = event;
event = booleans = undefined;
to.trigger = triggerTrue; // single-target profile with trigger:true
}
_aTweens.push(to);
targ.addListener(this);
tweenSuccess = true;
}
for (j in aProps) if (propsAdded.indexOf(aProps[j]+',')==-1) propsAdded+=(aProps[j]+',');
// TRACE TWEENS (lets you know if one or more props didn't get added)
if (outputLevel==3) {
var epstr:String = aEP.toString();
if (aProps.length>aEP.length) epstr += ('\n\t[NO-CHANGE PROPS DISCARDED. KEPT:'+sProps+']');
var evstr:String = '';
for (j in aEV) evstr=(((typeof aEV[j]=='string')?'"'+aEV[j]+'"':aEV[j]) + ', '+evstr);
FuseKitCommon.output('\n-'+(_sID())+' TWEEN:\n'+(['\t[getTimer():'+getTimer()+'] ','targ: '+targ, 'props: '+epstr, 'endVals: '+evstr, 'time: '+((seconds==undefined) ? _ZigoEngine.DURATION : seconds), 'easing: '+((ease==undefined) ? _ZigoEngine.EASING : ease), 'delay: '+((delay==undefined) ? 0 : delay), 'callbacks: '+((cbstr=='') ? '(none)':cbstr)]).join('\n\t'));
}
}
} // end targets loop(i)
if (seconds==undefined || _global.isNaN(seconds)==true) seconds = 0;
var time:Number = delay+seconds;
// time-based trigger: use a fake tween (trigger time must be less than tween duration+delay)
if (triggerTime!=undefined) {
// Special option to use a negative trigger time, which is counted back from the end of the tween
if (triggerTime<0) {
triggerTime += time;
}
if (triggerTime>0 && (time==0 || triggerTime