1  /**
     2   * properties.CurveModifiers
     3   * List of default special properties modifiers for the Tweener class
     4   * The function names are strange/inverted because it makes for easier debugging (alphabetic order). They're only for internal use (on this class) anyways.
     5   *
     6   * @author		Zeh Fernando, Nate Chatellier, Arthur Debert
     7   * @version		1.0.0
     8   */
     9  
    10  import caurina.transitions.Tweener;
    11  
    12  class caurina.transitions.properties.CurveModifiers {
    13  
    14  	/**
    15  	 * There's no constructor.
    16  	 */
    17  	public function CurveModifiers () {
    18  		trace ("This is an static class and should not be instantiated.")
    19  	}
    20  
    21  	/**
    22  	 * Registers all the special properties to the Tweener class, so the Tweener knows what to do with them.
    23  	 */
    24  	public static function init():Void {
    25  
    26  		// Bezier modifiers
    27  		Tweener.registerSpecialPropertyModifier("_bezier", _bezier_modifier, _bezier_get);
    28  	}
    29  
    30  
    31  	// ==================================================================================================================================
    32  	// SPECIAL PROPERTY MODIFIER functions ----------------------------------------------------------------------------------------------
    33  
    34  	// ----------------------------------------------------------------------------------------------------------------------------------
    35  	// _bezier
    36  
    37  	/**
    38  	 * Given the parameter object passed to this special property, return an array listing the properties that should be modified, and their parameters
    39  	 *
    40  	 * @param		p_obj				Object		Parameter passed to this property
    41  	 * @return							Array		Array listing name and parameter of each property
    42  	 */
    43  	public static function _bezier_modifier (p_obj:Object):Array {
    44  		var mList:Array = []; // List of properties to be modified
    45  		var pList:Array; // List of parameters passed, normalized as an array
    46  		if (p_obj instanceof Array) {
    47  			// Complex
    48  			pList = p_obj.concat();
    49  		} else {
    50  			pList = [p_obj];
    51  		}
    52  
    53  		var i:Number;
    54  		var istr:String;
    55  		var mListObj:Object = {}; // Object describing each property name and parameter
    56  
    57  		for (i = 0; i < pList.length; i++) {
    58  			for (istr in pList[i]) {
    59  				if (mListObj[istr] == undefined) mListObj[istr] = [];
    60  				mListObj[istr].push(pList[i][istr]);
    61  			}
    62  		}
    63  		for (istr in mListObj) {
    64  			mList.push({name:istr, parameters:mListObj[istr]});
    65  		}
    66  		return mList;
    67  	}
    68  
    69  	/**
    70  	 * Given tweening specifications (beging, end, t), applies the property parameter to it, returning new t
    71  	 *
    72  	 * @param		b					Number		Beginning value of the property
    73  	 * @param		e					Number		Ending (desired) value of the property
    74  	 * @param		t					Number		Current t of this tweening (0-1), after applying the easing equation
    75  	 * @param		p					Array		Array of parameters passed to this specific property
    76  	 * @return							Number		New t, with the p parameters applied to it
    77  	 */
    78  	public static function _bezier_get (b:Number, e:Number, t:Number, p:Array):Number {
    79  		// This is based on Robert Penner's code
    80  		if (p.length == 1) {
    81  			// Simple curve with just one bezier control point
    82  			return b + t*(2*(1-t)*(p[0]-b) + t*(e - b));
    83  		} else {
    84  			// Array of bezier control points, must find the point between each pair of bezier points
    85  			var ip:Number = Math.floor(t * p.length); // Position on the bezier list
    86  			var it:Number = (t - (ip * (1 / p.length))) * p.length; // t inside this ip
    87  			var p1:Number, p2:Number;
    88  			if (ip == 0) {
    89  				// First part: belongs to the first control point, find second midpoint
    90  				p1 = b;
    91  				p2 = (p[0]+p[1])/2;
    92  			} else if (ip == p.length - 1) {
    93  				// Last part: belongs to the last control point, find first midpoint
    94  				p1 = (p[ip-1]+p[ip])/2;
    95  				p2 = e;
    96  			} else {
    97  				// Any middle part: find both midpoints
    98  				p1 = (p[ip-1]+p[ip])/2;
    99  				p2 = (p[ip]+p[ip+1])/2;
   100  			}
   101  			return p1+it*(2*(1-it)*(p[ip]-p1) + it*(p2 - p1));
   102  		}
   103  	}
   104  }
   105