Skip to content
Browse files

Initial commit

  • Loading branch information...
0 parents commit 24f47bbb7f1cc6175a15352f1254ba4e80efd764 @danro committed Sep 15, 2010
41 ArrayProp.as
@@ -0,0 +1,41 @@
+
+import com.tweenman.BaseProp;
+
+class com.tweenman.ArrayProp extends BaseProp {
+
+ var props:Object;
+ var current:Object;
+
+ function construct () {
+ props = {};
+ }
+
+ function init () {
+ if (current == null) {
+ if (target instanceof Array) {
+ current = target;
+ } else if (target[id] instanceof Array) {
+ current = target[id];
+ }
+ }
+ var valueIsArray:Boolean = value instanceof Array;
+ if (!valueIsArray) return tween.valueError(id);
+ var count:Number = current.length;
+ var i:Number, prop:BaseProp;
+ for ( i = 0; i < count; i++ ) {
+ prop = new BaseProp();
+ props[ String(i) ] = prop;
+ prop.id = i;
+ prop.value = value[i];
+ prop.target = current;
+ prop.init();
+ }
+ }
+
+ function update ($position) {
+ var p:String;
+ for (p in props) {
+ props[p].update($position);
+ }
+ }
+}
67 BaseFilterProp.as
@@ -0,0 +1,67 @@
+
+import flash.display.BitmapData;
+import flash.filters.BitmapFilter;
+import com.tweenman.MultiProp;
+
+class com.tweenman.BaseFilterProp extends MultiProp {
+
+ var filterClass:Function;
+ var initializers:Object;
+
+ function init () {
+ var valid:Boolean = typeof(target) == "movieclip" || target instanceof Button || target instanceof TextField;
+ if (!valid) return tween.typeError(id, "MovieClip, Button, TextField");
+ if (value == null) value = defaults;
+ propList = [];
+ var p:String;
+ var initList:Object = {};
+ for ( p in value ) {
+ if (defaults[p] != null) {
+ propList.push(p);
+ } else if (initializers[p] != null) {
+ initList[p] = value[p];
+ delete value[p];
+ }
+ }
+ var filters:Array = target.filters;
+ var filterCount:Number = filters.length;
+ var filterFound:Boolean = false;
+ var i:Number;
+ for ( i = 0; i < filterCount; i++ ) {
+ if ( filters[i] instanceof filterClass ) {
+ current = filters[i];
+ filterFound = true;
+ }
+ }
+ if (!filterFound) {
+ current = new filterClass();
+ for ( p in defaults ) {
+ current[p] = defaults[p];
+ }
+ }
+ for ( p in initList ) {
+ current[p] = initList[p];
+ }
+ var valueIsArray:Boolean = value instanceof Array;
+ var valueIsObject:Boolean = typeof value == "object" && !valueIsArray;
+ if (!valueIsObject) return tween.valueError(id);
+ super.init();
+ }
+
+ function update ($position) {
+ super.update($position);
+ var filters:Array = target.filters;
+ var filterCount:Number = filters.length;
+ var i:Number;
+ for ( i = 0; i < filterCount; i++ ) {
+ if ( filters[i] instanceof filterClass ) {
+ filters[i] = current;
+ target.filters = filters;
+ return;
+ }
+ }
+ if (filters == null) filters = [];
+ filters.push(current);
+ target.filters = filters;
+ }
+}
28 BaseProp.as
@@ -0,0 +1,28 @@
+
+import com.tweenman.Tween;
+
+class com.tweenman.BaseProp {
+
+ var id:Object;
+ var tween:Tween;
+ var start:Number;
+ var change:Number;
+ var target:Object;
+ var value:Object;
+
+ function BaseProp () {
+ construct();
+ }
+
+ function construct () {}
+
+ function init () {
+ start = target[id];
+ change = typeof(value) == "number" ? value - start : Number(value);
+ }
+
+ function update ($position) {
+ var result:Number = start + ($position * change);
+ if (target[id] != result) target[id] = result;
+ }
+}
15 BevelFilterProp.as
@@ -0,0 +1,15 @@
+
+import flash.filters.BevelFilter;
+import com.tweenman.BaseFilterProp;
+import com.tweenman.HexColorProp;
+
+class com.tweenman.BevelFilterProp extends BaseFilterProp {
+
+ function init () {
+ filterClass = BevelFilter;
+ defaults = { distance: 4.0, angle: 45, highlightColor: 0xFFFFFF, highlightAlpha: 1.0, shadowColor: 0x000000, shadowAlpha: 1.0, blurX: 4.0, blurY: 4.0, strength: 0 };
+ classes = { highlightColor: HexColorProp, shadowColor: HexColorProp };
+ initializers = { quality: "", type: "", knockout: "" };
+ super.init();
+ }
+}
13 BlurFilterProp.as
@@ -0,0 +1,13 @@
+
+import flash.filters.BlurFilter;
+import com.tweenman.BaseFilterProp;
+
+class com.tweenman.BlurFilterProp extends BaseFilterProp {
+
+ function init () {
+ filterClass = BlurFilter;
+ defaults = { blurX: 0.0, blurY: 0.0 };
+ initializers = { quality: "" };
+ super.init();
+ }
+}
63 ColorFilterProp.as
@@ -0,0 +1,63 @@
+
+import flash.filters.ColorMatrixFilter;
+import com.tweenman.ArrayProp;
+import com.tweenman.ColorMatrix;
+
+class com.tweenman.ColorFilterProp extends ArrayProp {
+
+ private var defaults:Object = { brightness: 0, contrast: 0, saturation: 1, hue: 0, colorize: 0x000000,
+ colorizeAmount: 0, blend: false };
+
+ function init () {
+ var valid:Boolean = typeof(target) == "movieclip" || target instanceof Button || target instanceof TextField;
+ if (!valid) return tween.typeError(id, "MovieClip, Button, TextField");
+ if (value == null) value = defaults;
+ var cmf:ColorMatrixFilter;
+ var filters:Array = target.filters;
+ var filterCount:Number = filters.length;
+ var i:Number;
+ for ( i = 0; i < filterCount; i++ ) {
+ if ( filters[i] instanceof ColorMatrixFilter ) {
+ cmf = filters[i];
+ }
+ }
+ current = cmf == null ? ColorMatrix.IDENTITY.concat() : cmf.matrix.concat();
+ var cm:ColorMatrix = new ColorMatrix();
+ if (value.blend) cm.matrix = current.concat();
+ var p:String;
+ for (p in value) {
+ if (value[p] == null) continue;
+ switch (p) {
+ case "brightness": cm.adjustBrightness( value[p] ); break;
+ case "contrast": cm.adjustContrast( value[p] ); break;
+ case "saturation": cm.adjustSaturation( value[p] ); break;
+ case "hue": cm.adjustHue( value[p] ); break;
+ case "colorize":
+ case "colorizeAmount":
+ if (value.colorize == null) value.colorize = defaults.colorize;
+ if (value.colorizeAmount == null) value.colorizeAmount = defaults.colorizeAmount;
+ cm.adjustColorize( value.colorize, value.colorizeAmount );
+ break;
+ }
+ }
+ value = cm.matrix;
+ super.init();
+ }
+
+ function update ($position) {
+ super.update($position);
+ var filters:Array = target.filters;
+ var filterCount:Number = filters.length;
+ var i:Number;
+ for ( i = 0; i < filterCount; i++ ) {
+ if ( filters[i] instanceof ColorMatrixFilter ) {
+ filters[i].matrix = current.concat();
+ target.filters = filters;
+ return;
+ }
+ }
+ if (filters == null) filters = [];
+ filters.push( new ColorMatrixFilter( current.concat() ) );
+ target.filters = filters;
+ }
+}
70 ColorMatrix.as
@@ -0,0 +1,70 @@
+
+class com.tweenman.ColorMatrix {
+
+ static var IDENTITY:Array = [1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0];
+ var matrix:Array;
+
+ private static var r_lum:Number = 0.212671;
+ private static var g_lum:Number = 0.715160;
+ private static var b_lum:Number = 0.072169;
+
+ public function ColorMatrix () {
+ matrix = IDENTITY.concat();
+ }
+
+ function adjustBrightness (r:Number, g:Number, b:Number) {
+ g = (g == null) ? r : g;
+ b = (b == null) ? r : b;
+ concat( [1,0,0,0,r,0,1,0,0,g ,0,0,1,0,b ,0,0,0,1,0 ]);
+ }
+
+ function adjustContrast ( r:Number, g:Number, b:Number ) {
+ g = (g == null) ? r : g;
+ b = (b == null) ? r : b;
+ r+=1; g+=1; b+=1;
+ concat( [r,0,0,0,128*(1-r), 0,g,0,0,128*(1-g), 0,0,b,0,128*(1-b), 0,0,0,1,0 ]);
+ }
+
+ function adjustSaturation ( s:Number ) {
+ var i:Number=1-s;
+ var irlum:Number = i * r_lum;
+ var iglum:Number = i * g_lum;
+ var iblum:Number = i * b_lum;
+ concat( [irlum + s, iglum, iblum, 0, 0, irlum, iglum + s, iblum, 0, 0, irlum, iglum, iblum + s, 0, 0, 0, 0, 0, 1, 0 ]);
+ }
+
+ function adjustHue ( angle:Number ) {
+ angle *= Math.PI/180;
+ var c:Number = Math.cos( angle );
+ var s:Number = Math.sin( angle );
+ var f1:Number = 0.213;
+ var f2:Number = 0.715;
+ var f3:Number = 0.072;
+ concat( [(f1 + (c * (1 - f1))) + (s * (-f1)), (f2 + (c * (-f2))) + (s * (-f2)), (f3 + (c * (-f3))) + (s * (1 - f3)), 0, 0, (f1 + (c * (-f1))) + (s * 0.143), (f2 + (c * (1 - f2))) + (s * 0.14), (f3 + (c * (-f3))) + (s * -0.283), 0, 0, (f1 + (c * (-f1))) + (s * (-(1 - f1))), (f2 + (c * (-f2))) + (s * f2), (f3 + (c * (1 - f3))) + (s * f3), 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1] );
+ }
+
+ function adjustColorize ( rgb:Number, amount:Number ) {
+ if (amount == null) amount = 1;
+ var r:Number = ( ( rgb >> 16 ) & 0xff ) / 255;
+ var g:Number = ( ( rgb >> 8 ) & 0xff ) / 255;
+ var b:Number = ( rgb & 0xff ) / 255;
+ var inv_amount:Number = 1 - amount;
+ concat( [inv_amount + amount*r*r_lum, amount*r*g_lum, amount*r*b_lum, 0, 0, amount*g*r_lum, inv_amount + amount*g*g_lum, amount*g*b_lum, 0, 0, amount*b*r_lum,amount*b*g_lum, inv_amount + amount*b*b_lum, 0, 0, 0 , 0 , 0 , 1, 0] );
+ }
+
+ function concat ( mat:Array ) {
+ var temp:Array = [];
+ var i:Number = 0;
+ for (var y:Number = 0; y < 4; y++ ) {
+ for (var x:Number = 0; x < 5; x++ ) {
+ temp[i + x] = mat[i ] * matrix[x ] +
+ mat[i+1] * matrix[x + 5] +
+ mat[i+2] * matrix[x + 10] +
+ mat[i+3] * matrix[x + 15] +
+ (x == 4 ? mat[i+4] : 0);
+ }
+ i+=5;
+ }
+ matrix = temp;
+ }
+}
48 ColorProp.as
@@ -0,0 +1,48 @@
+
+import flash.geom.ColorTransform;
+import com.tweenman.MultiProp;
+import com.tweenman.HexColorProp;
+
+class com.tweenman.ColorProp extends MultiProp {
+
+ function init () {
+ var valid:Boolean = typeof(target) == "movieclip" || target instanceof Button || target instanceof TextField;
+ if (!valid) return tween.typeError(id, "MovieClip, Button, TextField");
+ defaults = { redMultiplier: 1.0, greenMultiplier: 1.0, blueMultiplier: 1.0, alphaMultiplier: 1.0,
+ redOffset: 0, greenOffset: 0, blueOffset: 0, alphaOffset: 0, brightness: 0,
+ tintColor: 0x000000, tintMultiplier: 0, burn: 0 };
+ if (value != null) {
+ if (value.brightness != null) {
+ value.redMultiplier = value.greenMultiplier = value.blueMultiplier = 1 - Math.abs(value.brightness);
+ value.burn = value.brightness > 0 ? value.brightness : 0;
+ }
+ if (value.burn != null) value.redOffset = value.greenOffset = value.blueOffset = 256 * value.burn;
+ if (value.tintColor != null) {
+ if (value.tintMultiplier == null) value.tintMultiplier = 1;
+ value.redOffset = (value.tintColor >> 16) * value.tintMultiplier;
+ value.greenOffset = ((value.tintColor >> 8) & 0xFF) * value.tintMultiplier;
+ value.blueOffset = (value.tintColor & 0xFF) * value.tintMultiplier;
+ }
+ if (value.tintMultiplier != null) {
+ value.redMultiplier = value.greenMultiplier = value.blueMultiplier = 1 - Math.abs(value.tintMultiplier);
+ }
+ }
+ if (value == null) value = defaults;
+ propList = [];
+ var p:String;
+ var ct = new ColorTransform();
+ for ( p in value ) {
+ if (p == "brightness" || p == "tintColor" || p == "tintMultiplier" || p == "burn") continue;
+ propList.push(p);
+ ct[p] = value[p];
+ }
+ value = ct;
+ current = target.transform.colorTransform;
+ super.init();
+ }
+
+ function update ($position) {
+ super.update($position);
+ target.transform.colorTransform = current;
+ }
+}
12 ConflictMap.as
@@ -0,0 +1,12 @@
+
+class com.tweenman.ConflictMap {
+
+ static var visible:Array = ["_alpha", "color"];
+ static var _alpha:Array = ["visible", "color"];
+ static var color:Array = ["visible", "_alpha"];
+
+ static var scale:Array = ["_xscale", "_yscale"];
+ static var _xscale:String = "scale";
+ static var _yscale:String = "scale";
+
+}
15 ConvolutionProp.as
@@ -0,0 +1,15 @@
+
+import flash.filters.ConvolutionFilter;
+import com.tweenman.BaseFilterProp;
+import com.tweenman.HexColorProp;
+
+class com.tweenman.ConvolutionProp extends BaseFilterProp {
+
+ function init () {
+ filterClass = ConvolutionFilter;
+ defaults = { divisor: 1.0, bias: 0.0, color: 0, alpha: 0.0 };
+ classes = { color: HexColorProp };
+ initializers = { matrix: "", matrixX: "", matrixY: "", preserveAlpha: "", clamp: "" };
+ super.init();
+ }
+}
15 DisplaceProp.as
@@ -0,0 +1,15 @@
+
+import flash.filters.DisplacementMapFilter;
+import com.tweenman.BaseFilterProp;
+import com.tweenman.HexColorProp;
+
+class com.tweenman.DisplaceProp extends BaseFilterProp {
+
+ function init () {
+ filterClass = DisplacementMapFilter;
+ defaults = { scaleX: 0.0, scaleY: 0.0, color: 0, alpha: 0.0 };
+ classes = { color: HexColorProp };
+ initializers = { mapBitmap: "", mapPoint: "", componentX: "", componentY: "", mode: "" };
+ super.init();
+ }
+}
15 DropShadowProp.as
@@ -0,0 +1,15 @@
+
+import flash.filters.DropShadowFilter;
+import com.tweenman.BaseFilterProp;
+import com.tweenman.HexColorProp;
+
+class com.tweenman.DropShadowProp extends BaseFilterProp {
+
+ function init () {
+ filterClass = DropShadowFilter;
+ defaults = { distance: 0.0, angle: 45, color: 0, alpha: 1.0, blurX: 0.0, blurY: 0.0, strength: 0 };
+ classes = { color: HexColorProp };
+ initializers = { quality: "", inner: "", knockout: "", hideObject: "" };
+ super.init();
+ }
+}
20 FrameProp.as
@@ -0,0 +1,20 @@
+
+import com.tweenman.BaseProp;
+
+class com.tweenman.FrameProp extends BaseProp {
+
+ function init () {
+ if (typeof(target) != "movieclip") return tween.typeError(id, "MovieClip");
+ start = target._currentframe;
+ if (typeof(value) == "number") {
+ change = value - start;
+ } else {
+ change = Number(value);
+ }
+ }
+
+ function update ($position) {
+ var newFrame:Number = int(start + ($position * change));
+ target.gotoAndStop(newFrame > 0 ? newFrame : 1);
+ }
+}
15 GlowFilterProp.as
@@ -0,0 +1,15 @@
+
+import flash.filters.GlowFilter;
+import com.tweenman.BaseFilterProp;
+import com.tweenman.HexColorProp;
+
+class com.tweenman.GlowFilterProp extends BaseFilterProp {
+
+ function init () {
+ filterClass = GlowFilter;
+ defaults = { alpha: 1, blurX: 0.0, blurY: 0.0, strength: 0, color: 0 };
+ classes = { color: HexColorProp };
+ initializers = { quality: "", inner: "", knockout: "" };
+ super.init();
+ }
+}
22 HexColorProp.as
@@ -0,0 +1,22 @@
+
+import com.tweenman.MultiProp;
+
+class com.tweenman.HexColorProp extends MultiProp {
+
+ function init () {
+ propList = ["r", "g", "b"];
+ current = hexToRgb( target[id] );
+ value = hexToRgb( value );
+ super.init();
+ }
+
+ function update ($position) {
+ super.update($position);
+ target[id] = (current.r << 16 | current.g << 8 | current.b);
+ }
+
+ function hexToRgb ($hex):Object {
+ if ($hex == null) $hex = 0x000000;
+ return { r: ($hex >> 16), g: ($hex >> 8) & 0xff, b: $hex & 0xff };
+ }
+}
18 InternalProps.as
@@ -0,0 +1,18 @@
+
+class com.tweenman.InternalProps {
+
+ static var time = 1;
+ static var duration = 1;
+ static var frames = 1;
+ static var ease = 1;
+ static var delay = 1;
+ static var onComplete = 1;
+ static var onCompleteParams = 1;
+ static var onUpdate = 1;
+ static var onUpdateParams = 1;
+ static var onStart = 1;
+ static var onStartParams = 1;
+ static var easeParams = 1;
+ static var proxiedEase = 1;
+
+}
46 MultiProp.as
@@ -0,0 +1,46 @@
+
+import com.tweenman.BaseProp;
+
+class com.tweenman.MultiProp extends BaseProp {
+
+ var props:Object;
+ var propList:Array;
+ var current:Object;
+ var defaults:Object;
+ var classes:Object;
+
+ function construct () {
+ props = {};
+ }
+
+ function init () {
+ var propCount:Number = propList.length;
+ var valueIsArray:Boolean = value instanceof Array;
+ var valueIsObject:Boolean = typeof value == "object" && !valueIsArray;
+ var i:Number, prop:BaseProp, propID:String, propClass:Function;
+ for ( i = 0; i < propCount; i++ ) {
+ propID = propList[i];
+ propClass = classes[propID] == null ? BaseProp : classes[propID];
+ prop = new propClass();
+ props[propID] = prop;
+ if (valueIsArray) {
+ prop.value = value[i];
+ } else if ( valueIsObject ) {
+ if (value[propID] == null) value[propID] = defaults[propID];
+ prop.value = value[propID];
+ } else {
+ prop.value = value;
+ }
+ prop.id = propID;
+ prop.target = current;
+ prop.init();
+ }
+ }
+
+ function update ($position) {
+ var p:String;
+ for (p in props) {
+ props[p].update($position);
+ }
+ }
+}
9 README
@@ -0,0 +1,9 @@
+package: com.tweenman
+
+TweenMan [AS2] ActionScript tweening library
+
+[Examples] http://github.com/danro/tweenman-examples
+
+[Documentation] http://github.com/danro/tweenman-as2/wiki
+
+[AS3 version] http://github.com/danro/tweenman-as3
26 RectangleProp.as
@@ -0,0 +1,26 @@
+
+import flash.geom.Rectangle;
+import com.tweenman.MultiProp;
+
+class com.tweenman.RectangleProp extends MultiProp {
+
+ function init () {
+ var valid:Boolean = typeof(target) == "movieclip" || target instanceof Button || target instanceof TextField;
+ if (!valid) return tween.typeError(id, "MovieClip, Button, TextField");
+ propList = ["x", "y", "width", "height"];
+ if (!target.scrollRect) {
+ var w:Number = Math.max(1, target._width * ( 100 / target._xscale ));
+ var h:Number = Math.max(1, target._height * ( 100 / target._yscale ));
+ target.scrollRect = new Rectangle( 0, 0, w, h );
+ }
+ if (isNaN(value[2]) || value[2] < 1) value[2] = 1; // restrict size to 1px
+ if (isNaN(value[3]) || value[3] < 1) value[3] = 1;
+ current = target.scrollRect;
+ super.init();
+ }
+
+ function update ($position) {
+ super.update($position);
+ target.scrollRect = current;
+ }
+}
11 ScaleProp.as
@@ -0,0 +1,11 @@
+
+import com.tweenman.MultiProp;
+
+class com.tweenman.ScaleProp extends MultiProp {
+
+ function init () {
+ propList = ["_xscale", "_yscale"];
+ current = target;
+ super.init();
+ }
+}
33 SoundProp.as
@@ -0,0 +1,33 @@
+
+import com.tweenman.BaseProp;
+
+class com.tweenman.SoundProp extends BaseProp {
+
+ private var previous:Object;
+
+ function init () {
+ /*
+ var typeFound:Boolean = false;
+ if (target == SoundMixer) {
+ typeFound = true;
+ } else {
+ for each (var soundType:Function in types) {
+ if (target is soundType) { typeFound = true; break; }
+ }
+ }
+ if (!typeFound) return tween.typeError(id, "Microphone, NetStream, SimpleButton, SoundChannel, SoundMixer, Sprite");
+ if (target.soundTransform == null) target.soundTransform = new SoundTransform();
+ previous = target;
+ target = target.soundTransform;
+ super.init();
+ */
+ }
+
+ function update ($position) {
+ /*
+ target = previous.soundTransform;
+ super.update($position);
+ previous.soundTransform = target;
+ */
+ }
+}
178 Tween.as
@@ -0,0 +1,178 @@
+
+import com.tweenman.TweenMan;
+import com.tweenman.BaseProp;
+import com.tweenman.ArrayProp;
+import com.tweenman.InternalProps;
+import com.tweenman.VirtualProps;
+
+class com.tweenman.Tween {
+
+ var id:String;
+ var targetID:String;
+ var target:Object;
+ var duration:Number;
+ var delay:Number;
+ var vars:Object;
+ var ease:Function;
+ var props:Object;
+ var children:Number;
+
+ var activated:Boolean;
+ var startTime:Number;
+ var initTime:Number;
+ var timeMethod:Function;
+ static var ZERO:Number = 0.001;
+
+ public function Tween ($target:Object, $vars:Object, $id:String, $targetID:String) {
+ target = $target;
+ vars = $vars;
+ id = $id;
+ targetID = $targetID;
+ children = 0;
+ if (!isNaN(vars.time)) vars.duration = vars.time;
+ duration = vars.duration;
+ delay = vars.delay;
+ if (isNaN(delay) || delay < 0) delay = 0;
+ if (!isNaN(vars.frames)) {
+ timeMethod = TweenMan.getFrames;
+ duration = int(vars.frames);
+ delay = int(delay);
+ } else {
+ timeMethod = getGlobalTimer;
+ }
+ if (isNaN(duration) || duration <= 0) duration = ZERO;
+ ease = typeof(vars.ease) == "function" ? vars.ease : TweenMan.defaultEase;
+ if (vars.easeParams != null) {
+ vars.proxiedEase = ease;
+ ease = easeProxy;
+ }
+ props = {};
+ initTime = timeMethod();
+ activated = false;
+ initProps();
+ if (duration == ZERO && delay == 0) {
+ startTime = 0;
+ render(1, 1);
+ } else {
+ TweenMan.enableRender();
+ }
+ }
+
+ function render ($t:Number, $f:Number) {
+ var elapsed:Number;
+ if (timeMethod == getGlobalTimer) {
+ elapsed = ($t - startTime) / 1000;
+ } else {
+ elapsed = $f - startTime;
+ }
+ if (elapsed > duration) elapsed = duration;
+ var position:Number = ease(elapsed, 0, 1, duration);
+ var p:String;
+ for (p in props) {
+ props[p].update(position);
+ }
+ if (vars.onUpdate != null) runCallback(vars.onUpdate, vars.onUpdateParams);
+ if (elapsed == duration) {
+ complete();
+ }
+ }
+
+ function get active():Boolean {
+ if (activated) {
+ return true;
+ } else {
+ if (timeMethod == getGlobalTimer) {
+ if ((timeMethod() - initTime) / 1000 > delay) {
+ activated = true;
+ startTime = initTime + (delay * 1000);
+ if (vars.onStart != null) runCallback(vars.onStart, vars.onStartParams);
+ if (duration == ZERO) startTime -= 1;
+ return true;
+ }
+ } else {
+ if (timeMethod() - initTime > delay) {
+ activated = true;
+ startTime = initTime + delay;
+ if (vars.onStart != null) runCallback(vars.onStart, vars.onStartParams);
+ if (duration == ZERO) startTime -= 1;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ function removeProp ($p:String):Boolean {
+ if (props[$p] == null) {
+ return false;
+ } else {
+ --children;
+ delete props[$p];
+ return true;
+ }
+ }
+
+ function typeError ($p, $type) {
+ trace("TweenMan says: target must be type [" + $type + "] to use [" + $p + "]");
+ removeProp($p);
+ }
+
+ function valueError ($p) {
+ trace("TweenMan says: unexpected value given for " + target + "[" + $p + "]");
+ removeProp($p);
+ }
+
+ private function complete () {
+ var onComplete = vars.onComplete;
+ var onCompleteParams = vars.onCompleteParams;
+ TweenMan.kill(this);
+ if (onComplete != null) runCallback(onComplete, onCompleteParams);
+ }
+
+ private function initProps() {
+ var prop:BaseProp;
+ var p:String;
+ for (p in vars) {
+ if ( InternalProps[p] != null ) {
+ continue;
+ } else {
+ var propClass:Function;
+ if ( VirtualProps[p] != null ) {
+ propClass = VirtualProps[p];
+ } else if ( p == "array" && target instanceof Array ) {
+ propClass = ArrayProp;
+ } else if ( target[p] != null ) {
+ propClass = BaseProp;
+ }
+ if ( propClass != null ) {
+ ++children;
+ prop = new propClass();
+ props[p] = prop;
+ prop.id = p;
+ prop.tween = this;
+ prop.target = target;
+ prop.value = vars[p];
+ prop.init();
+ } else {
+ trace("TweenMan says: target [" + target + "] does not contain property [" + p + "]");
+ }
+ }
+ }
+ }
+
+ private function easeProxy ():Number {
+ return vars.proxiedEase.apply(null, arguments.concat(vars.easeParams));
+ }
+
+ private function runCallback ($callback:Object, $params:Object) {
+ if ($callback instanceof Array) {
+ $callback[1].apply($callback[0], $params);
+ } else {
+ $callback.apply(null, $params);
+ }
+ }
+
+ private static function getGlobalTimer ():Number {
+ return getTimer();
+ }
+}
297 TweenMan.as
@@ -0,0 +1,297 @@
+/*
+ Version: 1.5 AS2
+ ---------------------------------------------------------------------------------
+ TweenMan is a complicated man, and no one understands him but his woman...
+ Initially influenced by Jack Doyle's TweenLite engine, TweenMan is now his own man
+ attempting to provide extended tweening functionality while remaining fit and slim.
+
+ Weighing in at approximately 10k compiled, TweenMan does a few things you probably
+ haven't seen other engines do. He can tween the scrollRect property of clips and
+ tween just about every filter's properties including the color of glows, bevels,
+ etc., and he can accomplish this by using time-based or frame-based animation.
+
+ For updates and examples, visit: http://www.tweenman.com
+
+ Author: Dan Rogers - dan@danro.net
+
+ Special Thanks: Jack Doyle for sharing TweenLite (greensock.com)
+ Mario Klingemann for sharing ColorMatrix (quasimondo.com)
+ Robert Penner for his AS2 easing functions (robertpenner.com)
+
+ Basic Usage
+ ---------------------------------------------------------------------------------
+ import com.tweenman.TweenMan;
+ import com.tweenman.easing.*;
+
+ // time-based _alpha tween
+ TweenMan.addTween(target, { time: 1, _alpha: 0 });
+
+ // frame-based scrollRect tween
+ TweenMan.addTween(target, { frames: 50, rectangle: [0,0,100,100], ease: Back.easeOut });
+
+ // time-based ColorMatrixFilter tween
+ TweenMan.addTween(target, { time: 2, colormatrix: { saturation: 0, contrast: 2 } });
+
+ // tween an array
+ var myArray:Array = [1, 4, 5, 6];
+ TweenMan.addTween(myArray, { time: 1, array: [0, 3, 4, 4] });
+
+ // remove tweens by property
+ TweenMan.removeTweens(target, "_alpha", "rectangle", "color");
+
+ // see if a tween is active
+ TweenMan.isTweening(target, "color");
+
+
+ Tween Properties
+ ---------------------------------------------------------------------------------
+ time time or duration of tween in seconds
+ duration eqivalent to time, duration in seconds
+ frames frame-based duration, overrides time/duration if set
+ ease easing function, default is Quartic.easeOut
+ delay delay before start, in seconds or frames depending on setting
+ onComplete callback function gets called when tween finishes
+ onCompleteParams params for onComplete function
+ onUpdate callback function gets called when tween updates
+ onUpdateParams params for onUpdate function
+ onStart callback function gets called when tween starts
+ onStartParams params for onStart function
+ easeParams params for ease function, mostly Back and Elastic
+ array if the target is an array, this property sets the end values
+
+
+ Virtual Properties
+ { prop: value } indicates tweenable sub-properties and default values
+ ---------------------------------------------------------------------------------
+ visible number or boolean same as _alpha but toggles visibility
+ frame number frame number of a MovieClip
+ scale number _xscale and _yscale properties combined
+ color object transform a target using ColorTransform
+ { redMultiplier: 1.0, greenMultiplier: 1.0, blueMultiplier: 1.0, alphaMultiplier: 1.0,
+ redOffset: 0, greenOffset: 0, blueOffset: 0, alphaOffset: 0, brightness: 0,
+ tintColor: 0x000000, tintMultiplier: 0, burn: 0 }
+
+ rectangle [0,0,100,100] scrollRect property of a DisplayObject
+ volume number volume of a MovieClip sound
+ pan number pan of a MovieClip sound
+
+ colormatrix object ColorMatrixFilter
+ { brightness: 0, contrast: 0, saturation: 1, hue: 0, colorize: 0x000000,
+ colorizeAmount: 0, blend: false } // set blend for additive blending
+
+ bevel object BevelFilter
+ { distance: 4.0, angle: 45, highlightColor: 0xFFFFFF, highlightAlpha: 1.0,
+ shadowColor: 0x000000, shadowAlpha: 1.0, blurX: 4.0, blurY: 4.0, strength: 0 }
+
+ blur object BlurFilter
+ { blurX: 0.0, blurY: 0.0 }
+
+ convolution object ConvolutionFilter
+ { divisor: 1.0, bias: 0.0, color: 0, alpha: 0.0 }
+
+ displace object DisplacementMapFilter
+ { scaleX: 0.0, scaleY: 0.0, color: 0, alpha: 0.0 }
+
+ dropshadow object DropShadowFilter
+ { distance: 0.0, angle: 45, color: 0, alpha: 1.0, blurX: 0.0, blurY: 0.0, strength: 0 }
+
+ glow object GlowFilter
+ { alpha: 1, blurX: 0.0, blurY: 0.0, strength: 0, color: 0 }
+
+
+ TweenMan is Licensed under the MIT License
+ ---------------------------------------------------------------------------------
+ Copyright (c) 2008 Dan Rogers
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+import com.tweenman.Tween;
+import com.tweenman.InternalProps;
+import com.tweenman.ConflictMap;
+import com.tweenman.easing.Quartic;
+
+class com.tweenman.TweenMan {
+
+ public static var version:String = "1.5 AS2";
+ public static var defaultEase:Function = Quartic.easeOut;
+
+ private static var listenerDepth:Number = 7777;
+ private static var listenerName:String = "$tweenManListener";
+ private static var renderEnabled:Boolean;
+ private static var cleanupTimer:Number;
+ private static var tweenDict:Object;
+ private static var frameCount:Number;
+ private static var tweenCount:Number;
+ private static var targetCount:Number;
+
+ public function TweenMan () {
+ if (_root[listenerName] != null) return;
+ _root[listenerName] = _root.createEmptyMovieClip(listenerName, listenerDepth);
+ _root[listenerName].onEnterFrame = TweenMan.enterFrameUpdate;
+ tweenDict = {};
+ resetCounts();
+ }
+
+ public static function addTween ($target:Object, $vars:Object) {
+ if (_root[listenerName] == null) new TweenMan();
+
+ if ($target == null) { trace("TweenMan says: target is null, vars [" + $vars + "]"); return; }
+
+ var targetID:String = getTargetID($target);
+
+ if (tweenDict[targetID] == null ) {
+ tweenDict[targetID] = {};
+ } else {
+ var removeParams:Array = [targetID];
+ for (var p:String in $vars) {
+ if ( InternalProps[p] != null ) continue;
+ removeParams.push(p);
+ if ( ConflictMap[p] != null ) {
+ removeParams = removeParams.concat(ConflictMap[p]);
+ }
+ }
+ removeTweens.apply(null, removeParams);
+ }
+ if (tweenDict[targetID] == null) tweenDict[targetID] = {};
+ var tweenID:String = "t" + String(++tweenCount);
+ tweenDict[targetID][tweenID] = new Tween($target, $vars, tweenID, targetID);
+ }
+
+ public static function removeTweens ($target:Object) {
+ var targetID:String = typeof($target) == "string" ? String($target) : getTargetID($target);
+ if ($target == null || tweenDict[targetID] == null) return;
+ arguments.shift();
+ if (arguments.length == 0) {
+ delete tweenDict[targetID];
+ } else {
+ var i:Number, p:String, tweenID:String, tween:Tween, removed:Boolean;
+ var count:Number = arguments.length;
+ for (i = 0; i<count; i++) {
+ p = arguments[i];
+ for (tweenID in tweenDict[targetID]) {
+ tween = tweenDict[targetID][tweenID];
+ removed = tween.removeProp(p);
+ if (removed && tween.children == 0) kill(tween);
+ }
+ }
+ }
+ }
+
+ public static function removeAll () {
+ tweenDict = {};
+ killGarbage();
+ }
+
+ public static function isTweening ($target:Object, $prop:String):Boolean {
+ killGarbage();
+ var targetID:String = getTargetID($target);
+ if (tweenDict[targetID] == null) return false;
+ if ($prop == null) return true;
+ var tweenID:String, tween:Tween;
+ for (tweenID in tweenDict[targetID]) {
+ tween = tweenDict[targetID][tweenID];
+ if (tween.props[$prop] != null) return true;
+ }
+ return false;
+ }
+
+ public static function killGarbage () {
+ var count:Number = 0;
+ var found:Boolean;
+ var targID:String, tweenID:String;
+ for (targID in tweenDict) {
+ found = false;
+ for (tweenID in tweenDict[targID]) {
+ found = true;
+ break;
+ }
+ if (!found) {
+ delete tweenDict[targID];
+ } else {
+ ++count;
+ }
+ }
+ if (count == 0) {
+ disableRender();
+ }
+ }
+
+ public static function getTargetID ($target:Object):String {
+ if (typeof($target) == "movieclip") return String($target);
+ var targID:String, tweenID:String, tween:Tween;
+ for (targID in tweenDict) {
+ for (tweenID in tweenDict[targID]) {
+ tween = tweenDict[targID][tweenID];
+ if (tween.target === $target) return targID;
+ }
+ }
+ ++targetCount;
+ return "targetID:"+targetCount;
+ }
+
+ static function kill ($tween:Tween) {
+ var targetID:String = $tween.targetID;
+ var tweenID:String = $tween.id;
+ if (tweenDict[targetID] == null || tweenDict[targetID][tweenID] == null) return;
+ delete tweenDict[targetID][tweenID];
+ }
+
+ static function getFrames ():Number {
+ return frameCount;
+ }
+
+ static function enableRender () {
+ if (!renderEnabled) {
+ clearInterval(cleanupTimer);
+ cleanupTimer = setInterval(TweenMan.killGarbage, 2000);
+ renderEnabled = true;
+ }
+ }
+
+ static function disableRender () {
+ clearInterval(cleanupTimer);
+ resetCounts();
+ renderEnabled = false;
+ }
+
+ private static function enterFrameUpdate () {
+ if (!renderEnabled) return;
+ ++frameCount;
+ render();
+ }
+
+ private static function render () {
+ var t:Number = getTimer();
+ var f:Number = frameCount;
+ var targID:String, tweenID:String, tween:Tween;
+ for (targID in tweenDict) {
+ for (tweenID in tweenDict[targID]) {
+ tween = tweenDict[targID][tweenID];
+ if (tween.active) tween.render(t,f);
+ }
+ }
+ }
+
+ private static function resetCounts () {
+ frameCount = 0;
+ tweenCount = 0;
+ targetCount = 0;
+ }
+}
27 VirtualProps.as
@@ -0,0 +1,27 @@
+
+import com.tweenman.*;
+
+class com.tweenman.VirtualProps {
+
+ static var visible:Function = VisibleProp;
+ static var frame:Function = FrameProp;
+ static var scale:Function = ScaleProp;
+ static var rectangle:Function = RectangleProp;
+ static var color:Function = ColorProp;
+ static var volume:Function = SoundProp;
+ static var pan:Function = SoundProp;
+
+ static var colormatrix:Function = ColorFilterProp;
+ static var bevel:Function = BevelFilterProp;
+ static var blur:Function = BlurFilterProp;
+ static var convolution:Function = ConvolutionProp;
+ static var displace:Function = DisplaceProp;
+ static var dropshadow:Function = DropShadowProp;
+ static var glow:Function = GlowFilterProp;
+
+ static var backgroundColor:Function = HexColorProp;
+ static var borderColor:Function = HexColorProp;
+ static var textColor:Function = HexColorProp;
+ static var hexColor:Function = HexColorProp;
+
+}
21 VisibleProp.as
@@ -0,0 +1,21 @@
+
+import com.tweenman.BaseProp;
+
+class com.tweenman.VisibleProp extends BaseProp {
+
+ function init () {
+ id = "_alpha";
+ if (value === true) value = 100;
+ if (value === false) value = 0;
+ super.init();
+ }
+
+ function update ($position) {
+ super.update($position);
+ if (target._alpha < 0.01) {
+ if (target._visible) target._visible = false;
+ } else if (target._alpha > 0.01) {
+ if (!target._visible) target._visible = true;
+ }
+ }
+}
15 easing/Back.as
@@ -0,0 +1,15 @@
+class com.tweenman.easing.Back {
+ static function easeIn (t:Number, b:Number, c:Number, d:Number, s:Number):Number {
+ if (s == undefined) s = 1.70158;
+ return c*(t/=d)*t*((s+1)*t - s) + b;
+ }
+ static function easeOut (t:Number, b:Number, c:Number, d:Number, s:Number):Number {
+ if (s == undefined) s = 1.70158;
+ return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
+ }
+ static function easeInOut (t:Number, b:Number, c:Number, d:Number, s:Number):Number {
+ if (s == undefined) s = 1.70158;
+ if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
+ return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
+ }
+}
20 easing/Bounce.as
@@ -0,0 +1,20 @@
+class com.tweenman.easing.Bounce {
+ static function easeOut (t:Number, b:Number, c:Number, d:Number):Number {
+ if ((t/=d) < (1/2.75)) {
+ return c*(7.5625*t*t) + b;
+ } else if (t < (2/2.75)) {
+ return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
+ } else if (t < (2.5/2.75)) {
+ return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
+ } else {
+ return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
+ }
+ }
+ static function easeIn (t:Number, b:Number, c:Number, d:Number):Number {
+ return c - com.tweenman.easing.Bounce.easeOut (d-t, 0, c, d) + b;
+ }
+ static function easeInOut (t:Number, b:Number, c:Number, d:Number):Number {
+ if (t < d/2) return com.tweenman.easing.Bounce.easeIn (t*2, 0, c, d) * .5 + b;
+ else return com.tweenman.easing.Bounce.easeOut (t*2-d, 0, c, d) * .5 + c*.5 + b;
+ }
+}
12 easing/Circular.as
@@ -0,0 +1,12 @@
+class com.tweenman.easing.Circular {
+ static function easeIn (t:Number, b:Number, c:Number, d:Number):Number {
+ return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
+ }
+ static function easeOut (t:Number, b:Number, c:Number, d:Number):Number {
+ return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
+ }
+ static function easeInOut (t:Number, b:Number, c:Number, d:Number):Number {
+ if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
+ return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
+ }
+}
12 easing/Cubic.as
@@ -0,0 +1,12 @@
+class com.tweenman.easing.Cubic {
+ static function easeIn (t:Number, b:Number, c:Number, d:Number):Number {
+ return c*(t/=d)*t*t + b;
+ }
+ static function easeOut (t:Number, b:Number, c:Number, d:Number):Number {
+ return c*((t=t/d-1)*t*t + 1) + b;
+ }
+ static function easeInOut (t:Number, b:Number, c:Number, d:Number):Number {
+ if ((t/=d/2) < 1) return c/2*t*t*t + b;
+ return c/2*((t-=2)*t*t + 2) + b;
+ }
+}
21 easing/Elastic.as
@@ -0,0 +1,21 @@
+class com.tweenman.easing.Elastic {
+ static function easeIn (t:Number, b:Number, c:Number, d:Number, a:Number, p:Number):Number {
+ if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
+ if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
+ else var s = p/(2*Math.PI) * Math.asin (c/a);
+ return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+ }
+ static function easeOut (t:Number, b:Number, c:Number, d:Number, a:Number, p:Number):Number {
+ if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
+ if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
+ else var s = p/(2*Math.PI) * Math.asin (c/a);
+ return (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b);
+ }
+ static function easeInOut (t:Number, b:Number, c:Number, d:Number, a:Number, p:Number):Number {
+ if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
+ if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
+ else var s = p/(2*Math.PI) * Math.asin (c/a);
+ if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+ return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
+ }
+}
14 easing/Exponential.as
@@ -0,0 +1,14 @@
+class com.tweenman.easing.Exponential {
+ static function easeIn (t:Number, b:Number, c:Number, d:Number):Number {
+ return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
+ }
+ static function easeOut (t:Number, b:Number, c:Number, d:Number):Number {
+ return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+ }
+ static function easeInOut (t:Number, b:Number, c:Number, d:Number):Number {
+ if (t==0) return b;
+ if (t==d) return b+c;
+ if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
+ return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
+ }
+}
14 easing/Linear.as
@@ -0,0 +1,14 @@
+class com.tweenman.easing.Linear {
+ static function easeNone (t:Number, b:Number, c:Number, d:Number):Number {
+ return c*t/d + b;
+ }
+ static function easeIn (t:Number, b:Number, c:Number, d:Number):Number {
+ return c*t/d + b;
+ }
+ static function easeOut (t:Number, b:Number, c:Number, d:Number):Number {
+ return c*t/d + b;
+ }
+ static function easeInOut (t:Number, b:Number, c:Number, d:Number):Number {
+ return c*t/d + b;
+ }
+}
12 easing/Quadratic.as
@@ -0,0 +1,12 @@
+class com.tweenman.easing.Quadratic {
+ static function easeIn (t:Number, b:Number, c:Number, d:Number):Number {
+ return c*(t/=d)*t + b;
+ }
+ static function easeOut (t:Number, b:Number, c:Number, d:Number):Number {
+ return -c *(t/=d)*(t-2) + b;
+ }
+ static function easeInOut (t:Number, b:Number, c:Number, d:Number):Number {
+ if ((t/=d/2) < 1) return c/2*t*t + b;
+ return -c/2 * ((--t)*(t-2) - 1) + b;
+ }
+}
12 easing/Quartic.as
@@ -0,0 +1,12 @@
+class com.tweenman.easing.Quartic {
+ static function easeIn (t:Number, b:Number, c:Number, d:Number):Number {
+ return c*(t/=d)*t*t*t + b;
+ }
+ static function easeOut (t:Number, b:Number, c:Number, d:Number):Number {
+ return -c * ((t=t/d-1)*t*t*t - 1) + b;
+ }
+ static function easeInOut (t:Number, b:Number, c:Number, d:Number):Number {
+ if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
+ return -c/2 * ((t-=2)*t*t*t - 2) + b;
+ }
+}
12 easing/Quintic.as
@@ -0,0 +1,12 @@
+class com.tweenman.easing.Quintic {
+ static function easeIn (t:Number, b:Number, c:Number, d:Number):Number {
+ return c*(t/=d)*t*t*t*t + b;
+ }
+ static function easeOut (t:Number, b:Number, c:Number, d:Number):Number {
+ return c*((t=t/d-1)*t*t*t*t + 1) + b;
+ }
+ static function easeInOut (t:Number, b:Number, c:Number, d:Number):Number {
+ if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
+ return c/2*((t-=2)*t*t*t*t + 2) + b;
+ }
+}
11 easing/Sine.as
@@ -0,0 +1,11 @@
+class com.tweenman.easing.Sine {
+ static function easeIn (t:Number, b:Number, c:Number, d:Number):Number {
+ return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
+ }
+ static function easeOut (t:Number, b:Number, c:Number, d:Number):Number {
+ return c * Math.sin(t/d * (Math.PI/2)) + b;
+ }
+ static function easeInOut (t:Number, b:Number, c:Number, d:Number):Number {
+ return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
+ }
+}

0 comments on commit 24f47bb

Please sign in to comment.
Something went wrong with that request. Please try again.