import com.mosesSupposes.fuse.FuseKitCommon;
import com.mosesSupposes.fuse.ZigoEngine;
/**
* 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
*
* Documentation explains engine events. Class is private to engine but code documents methods & properties.
*
* @usage
* Engine events:
* {@link com.mosesSupposes.fuse.ZigoEngine#doTween} allows for automated callbacks. In most cases, callbacks are
* ideal because only one targeted function-call is needed. But in situations where a tween's state-change might
* need to be heard by a number of listener scopes, events can be more flexible.
* Events dispatched by ZigoEngine (see {@link com.mosesSupposes.fuse.ZigoEngine#addListener} for more info):
*
onTweenInterrupt
onTweenStart
onTweenUpdate
onTweenEnd
ZigoEngine.initialize
step if simpleSetup
was used.
* (Otherwise you need to initialize targets so they are able to accept listeners prior to tweening.)
* var myListener:Object = { * onTweenStart:function(o:Object):Void { * trace("Tween started on:"+o.target._name+" ["+o.props.toString()+"]"); * }, * onTweenUpdate:function(o:Object):Void { * trace("Tween updating on:"+o.target._name+" ["+o.props.toString()+"]"); * }, * onTweenEnd:function(o:Object):Void { * trace("Tween completed on:"+o.target._name+" ["+o.props.toString()+"]"); * } * }; * * // if simpleSetup was not used, initialize targets first to accept listeners * ZigoEngine.initialize(clip1, clip2); * * clip1.addListener(myListener); * clip2.addListener(myListener); * ZigoEngine.doTween(clip1,"_alpha",0,2); * ZigoEngine.doTween(clip2,"_scale",200,2); **
{target:Object, props:Array}
.ZigoEngine.removeTween
.
* @param targs One or more targets or the keyword 'ALL', null is rejected.
* @param props One or more props in any valid format, no value indicates all.
* @param noInit Internal flag used during addTween cycle to suppress engine reboot.
*/
public function removeTween(targs:Object, props:Object, noInit:Boolean):Void {
// interrupted properties
var ip:Object = {};
// condense code then reset faster locals.
var o:Object = paramsObj(targs,props);
if (o.none==true) return;
var all:Boolean = o.all;
var allp:Boolean = o.allprops;
// may actually be Object or Array
var tg:Object = ((all==true) ? tweens : Object(o.tg));
var missing:Boolean = false;
for (var j:String in tg) {
var id:String = ((all==true) ? j : String((tg[j]).__zigoID__));
var to:Object = tweens[id];
var po:Object = (allp==true) ? to.props : o.props;
for (var i:String in po) {
var allcolor:Boolean = (i==FuseKitCommon.ALLCOLOR && to.colorProp!=undefined);
if (to.props[i]!=undefined || allcolor==true) {
if(ip[id]==null) ip[id] = [];
(ip[id]).unshift(i);
if (i==to.colorProp || allcolor==true) {
delete (to.props[to.colorProp]);
delete (to.colorProp);
}
else delete (to.props[i]);
to.numProps--;
if (to.numProps<=0) {
missing = true;
break;
}
}
}
}
if ((ZigoEngine['_listeners']).length>0) {
for (var k:String in ip) {
// removed movieclips often query as not undefined, so check addProperty which is a base Object method in flash
var t:Object = (tweens[k]).targ;
(ZigoEngine['broadcastMessage'])('onTweenInterrupt',
{target:((typeof t.addProperty=='function')?t:'[MISSING("'+(tweens[k]).targID+'")]'),
props:ip[k],
__zigoID__:(tweens[k]).targZID});
}
}
// noInit param used during doTween so engine stays active
if (missing==true) cleanUp(noInit);
}
/**
* @exclude
* Internal method used by ZigoEngine.pauseTween
, unpauseTween
, rewTween
, ffTween
methods.
* @param type string cuing which action is being requested by the engine class.
* @param targs one or more targets or the keyword 'ALL', null is rejected.
* @param props one or more props in any valid format, no value indicates all.
* @param pauseFlag whether to pause after rewind.
* @param suppressStartEvents if true onTweenStart and startfunc callbacks are not refired upon rewind; if false or undefined the events are refired.
*/
public function alterTweens(type:String, targs:Object, props:Object, pauseFlag:Boolean, suppressStartEvents:Boolean):Void
{
if (type=='lock') {
(tweens[String(targs.__zigoID__)]).locked = Boolean(props==true);
return;
}
// condense code then reset faster locals.
var o:Object = paramsObj(targs,props);
if (o.none==true) return;
var all:Boolean = o.all;
var allp:Boolean = o.allprops;
var tg:Object = (all==true) ? tweens : Object(o.tg);
var hits:Number = 0;
for (var j:String in tg) {
var id:String = ((all==true) ? j : String((tg[j]).__zigoID__));
var to:Object = tweens[id];
var po:Object = (allp==true) ? to.props : o.props;
if (po.ALLCOLOR==true) { // swap 'allcolor' keyword with actual colorprop.
po[to.colorProp] = true;
delete po.ALLCOLOR;
}
for (var prop:String in po) {
hits++;
var t:Object = to.props[prop];
if (type=='rewind') {
if (pauseFlag==true) t.pt = now;
// reset start time
t.ts = now;
// enable onTweenStart and startfunc to refire when rewound
if (suppressStartEvents!=true) {
t.sf = false;
if (t.scb!=undefined) t.scb.fired = false;
}
}
else if (type=='ff') {
t.pt = -1;
// back up start time so update will think it's done.
t.ts = now - t.d;
}
else if (type=='pause') {
if(t.pt==-1) t.pt = now;
}
else if (type=='unpause') {
if(t.pt!=-1) {
// update start times
t.ts = now-(t.pt-t.ts);
t.pt = -1;
}
}
}
}
if (type=='ff' && hits>0) update();
else if (type=='rewind' && hits>0) update(true);
}
/**
* @exclude
* Internal method used by ZigoEngine.isTweenPaused
, isTweenLocked
, isTweening
methods.
* @param type string cuing which status is being requested by the engine class
* @param targ a target to query for requested status
* @param param one or more props in any valid format, no value indicates all
* @return dynamic value
*/
public function getStatus(type:String, targ:Object, param:Object):Object
{
if (targ==null) return null;
var all:Boolean = (String(targ).toUpperCase()==FuseKitCommon.ALL);
var t:Object = tweens[String(targ.__zigoID__)];
switch (type) {
case 'paused':
var props:Object = t.props;
if (param!=null) {
if (props[String(param)]==undefined) return false;
return Boolean((props[String(param)]).pt!=-1);
}
for (var i:String in props) {
if ((props[i]).pt!=-1) return true;
}
return false;
case 'active':
if (param==null) return Boolean(t!=undefined);
if (String(param).toUpperCase()==FuseKitCommon.ALLCOLOR) return Boolean(t.colorProp!=undefined);
return Boolean(t.props[String(param)]!=undefined);
case 'count':
if (!all) return (t.numProps);
var count:Number = 0;
for (var i:String in tweens) count+=(tweens[i]).numProps;
return count;
case 'locked':
return t.locked;
}
}
/**
* @exclude
* The primary on-pulse animation updating and event dispatching method.
* @param force - used in rewTween to force paused tweens to update
*/
public function update(force:Boolean):Void
{
// loop through tweens
var scb:Object = {};
var ucb:Object = {};
var ecb:Object = {};
var sp:Object = {};
var up:Object = {};
var ep:Object = {};
// for cleanUp()
var missing:Boolean = false;
var RR:Boolean = ZigoEngine.ROUND_RESULTS;
for (var i:String in tweens) {
var to:Object = tweens[i];
var targ:Object = to.targ;
var props:Object = to.props;
var evtFlag:Boolean = (targ._listeners.length>0);
if (targ.__zigoID__==undefined) {
missing = true;
// removed movieclips often query as not undefined, so check addProperty which is a base Object method in flash
if ((ZigoEngine['_listeners']).length>0) {
var plist:Array = [];
for (var prop:String in props) plist.unshift(prop);
(ZigoEngine['broadcastMessage'])('onTweenInterrupt',
{ target:((typeof targ.addProperty=='function')?targ:'[MISSING:'+to.targID+']'),
props:plist, __zigoID__:to.targZID });
}
continue;
}
for (var prop:String in props) {
var t:Object = props[prop];
// delayed tween waiting / skip processing paused tween
if ((t.ts>now || t.pt!=-1) && force!=true) continue;
var done:Boolean = (now >= (t.ts+t.d));
// run easing calc or set to endval if done.
if(t.c==-1) {
var val:Number;
if (done==true) {
val = (t.ps+t.ch);
if (t.cycles>1 || t.cycles==0) {
if (t.cycles>1) t.cycles--;
t.ps = val;
t.ch = -t.ch;
t.ts = now;
done = false;
}
}
else {
val = (t.ef((now-t.ts), t.ps, t.ch, t.d, t.e1, t.e2));
}
if (_global.isNaN(val)==false) {
if (RR==true) {
val = (Math.round(Number(val)));
}
if (t.special!=true) {
// set all other single value properties
targ[prop] = val;
}
else {
if (t.fmp!=-1) {
t.fmp.setFilterProp(targ,prop,val);
}
else if (prop=='_bezier_') {
var bz:Object = t.bz;
targ._x = (bz.sx + val*(2*(1-val)*bz.ctrlx + val*bz.chx));
targ._y = (bz.sy + val*(2*(1-val)*bz.ctrly + val*bz.chy));
}
// enables frameTo if MC not extended with _frame.
else if (prop=='_frame') {
MovieClip(targ).gotoAndStop(Math.round(val));
}
}
}
}
else {
// colortransform
var tt:Object = {};
var loop:Boolean = (done==true && (t.cycles>1 || t.cycles==0));
for (var j:String in t.ch) {
var cv:Number = t.ch[j];
if (done==true) {
tt[j] = (t.ps[j]+cv);
if (loop==true) {
t.ch[j] = -cv;
}
}
else {
tt[j] = (t.ef((now-t.ts), t.ps[j], cv, t.d, t.e1, t.e2));
}
if (_global.isNaN(tt[j])==false) {
if (RR==true) {
tt[j] = Math.round(tt[j]);
}
if (t.fmp==-1) {
t.c.setTransform(tt);
}
else {
//fmp color prop
var rgb:Number = (tt.rb << 16 | tt.gb << 8 | tt.bb);// (rgb number built from transobj)
t.fmp.setFilterProp(targ, prop, rgb);
}
}
}
if (loop==true) {
// perf.hit for this feature is very slight - slight drop (~1fps) per 200 r+g+b tweens.
if (t.cycles>1) t.cycles--;
done = false;
t.ts = now;
t.ps = tt;
}
}
// start-event-fired flag; may be reset during rewind.
if (t.sf==false) {
if (evtFlag==true) {
if (sp[i]==undefined) sp[i] = [targ,[]];
(sp[i][1]).unshift(prop);
}
t.sf = true;
}
// start-callback-fired flag; may be reset during rewind.
if(t.scb.fired==false) {
scb[String(t.scb.id)] = t.scb;
t.scb.fired = true;
}
if (evtFlag==true) {
/* although it's more complex to store targets, events fired very well may
* add or remove tweens in the engine. So, it's best to not cross-reference
* back to the tween-list during the event loops since it might change. */
if (up[i]==undefined) up[i] = [targ,[]];
(up[i][1]).unshift(prop);
}
if(t.ucb!=undefined) {
ucb[String(t.ucb.id)] = t.ucb;
}
if (done==true) {
if (evtFlag==true) {
if (ep[i]==undefined) ep[i] = [targ,[]];
(ep[i][1]).unshift(prop);
}
if(t.ecb!=undefined) {
ecb[String(t.ecb.id)] = t.ecb;
}
delete props[prop];
if (prop==to.colorProp) delete (to.colorProp);
to.numProps--;
// cue cleanUp();
if (to.numProps<=0) missing = true;
} // end loop through props [prop]
} // end looop through targets [i]
}
// broadcast amalgamated events & execute callbacks once per target
for (var i:String in sp) (sp[i][0]).broadcastMessage('onTweenStart', {target:(sp[i][0]), props:sp[i][1]});
for (var i:String in scb) (scb[i]).f.apply((scb[i]).s, (scb[i]).a);
for (var i:String in up) (up[i][0]).broadcastMessage('onTweenUpdate', {target:(up[i][0]), props:up[i][1]});
for (var i:String in ucb) (ucb[i]).f.apply((ucb[i]).s, (ucb[i]).a);
for (var i:String in ep) (ep[i][0]).broadcastMessage('onTweenEnd', {target:(ep[i][0]), props:ep[i][1]});
for (var i:String in ecb) (ecb[i]).f.apply((ecb[i]).s, (ecb[i]).a);
// cleanup
if (missing) cleanUp();
// update timer
now = getTimer();
}
/**
* @exclude
* Clean up tweens when targets go missing, this method helps reboot the manager when 're-testing' a published swf
* @param noInit prevents engine deinit call during addTween
*/
public function cleanUp(noInit:Boolean):Void {
for (var i:String in tweens) {
var targ:Object = (tweens[i]).targ;
if ((tweens[i]).numProps<=0 || targ.__zigoID__==undefined) {
if (targ!=undefined && targ.tween==undefined && noInit!=true) {// If object was not initialized with shortcuts, clear its tweenable status.
ZigoEngine.deinitializeTargets(targ);
}
delete (tweens[i]);
numTweens--;
}
}
if(numTweens<=0) {
numTweens = 0;
delete tweens;
tweens = {};
// last tween removed, turn off the updater
if (noInit!=true) ZigoEngine.__mgrRelay(this,'setup',[true]);
}
}
/**
* @exclude
* helper for alterTweens, removeTween, and ZigoEngine.doTween to process & consolidate properties.
* @param targs targets as passed by user
* @param props props as passed by user
* @param endVals end-values as passed to ZigoEngine.doTween
* @return a custom object formatted for internal use
*/
public function paramsObj(targs:Object, props:Object, endvals:Object):Object {
var o:Object = {};
o.all = (String(targs).toUpperCase()==FuseKitCommon.ALL);
o.none = Boolean(targs==null);
if (o.all==true) {
// return a single fake target to accomodate for-in 'targs' loops
o.tg = [null];
}
else {
o.tg = ((targs instanceof Array) ? targs:[targs]);
for (var i:String in o.tg) {
var t:Object = o.tg[i];
if (t==null || !(typeof t=='object' || typeof t=='movieclip')) {
// clean out dud targets
o.tg.splice(Number(i),1);
}
}
}
o.allprops = (props==null);
var pa:Array;
var va:Array;
var pobj:Object = {};
if (o.allprops==false) {
if (typeof props=='string' && (String(props).indexOf(' ')>-1 || String(props).indexOf(',')>-1)) {
// enable multiple comma-delimited string-relative end-values
props = (String(((props).split(' ')).join('')).split(','));
}
pa = (props instanceof Array) ? ((props).slice()) : [props];
// end-value proceessing for ZigoEngine class
// (moved here to accompany complex props changes due to overlaps/conflicts/redundancy.)
if (endvals!=undefined) {
if (typeof endvals=='string' && (String(endvals).indexOf(' ')>-1 || String(endvals).indexOf(',')>-1)) {
// enable multiple comma-delimited string-relative end-values
endvals = (String(((endvals).split(' ')).join('')).split(','));
}
va = (endvals instanceof Array) ? ((endvals).slice()) : [endvals];
// too few endvalues passed
while (va.length