1 /***************************************
  2  * Copyright 2011, 2012 GlobWeb contributors.
  3  *
  4  * This file is part of GlobWeb.
  5  *
  6  * GlobWeb is free software: you can redistribute it and/or modify
  7  * it under the terms of the GNU Lesser General Public License as published by
  8  * the Free Software Foundation, version 3 of the License, or
  9  * (at your option) any later version.
 10  *
 11  * GlobWeb is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 14  * GNU Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU General Public License
 17  * along with GlobWeb. If not, see <http://www.gnu.org/licenses/>.
 18  ***************************************/
 19 
 20  define(['./Utils','./Animation','./Numeric'], function(Utils,Animation,Numeric) {
 21 
 22 /**************************************************************************************************************/
 23 
 24 /** @constructor
 25   SegmentedAnimation is an animation defined with segments.
 26   Each segment has a [start,end] pair of 't' value and a [start,end] pair of
 27   values that will be interpolated with the interpolator set on the segment.
 28   When the animation runs, a t parameter is mapped to [0,1] according to
 29   current time and animation duration.
 30   The current segment is then looked up with that 't' value and used to interpolate
 31   the animation's current value.
 32  */
 33 var SegmentedAnimation = function(duration, valueSetter)
 34 {
 35     // Call ancestor constructor
 36     Animation.prototype.constructor.call(this);
 37 
 38     this.segments = [];
 39     this.duration = duration;
 40     this.valueSetter = valueSetter;
 41 }
 42 
 43 /**************************************************************************************************************/
 44 
 45 Utils.inherits(Animation,SegmentedAnimation);
 46 
 47 /**************************************************************************************************************/
 48 
 49 /** @constructor
 50   Segment struct
 51 */
 52 var Segment = function(start, startValue, end, endValue, interpolator)
 53 {
 54     this.start = start;
 55     this.startValue = startValue;
 56     this.end = end;
 57     this.endValue = endValue;
 58     this.interpolator = interpolator;
 59 }
 60 
 61 /**************************************************************************************************************/
 62 
 63 /*
 64 	Adds a new segment to the animation.
 65 	start, end are 't' values at which the segment will be the current segment
 66 	startValue, endValue are animation values at 't'=start and 't'=end
 67 	interpolator is the function that will be called to interpolate bewteen startValue and endValue.
 68 */
 69 SegmentedAnimation.prototype.addSegment = function(start, startValue, end, endValue, interpolator)
 70 {
 71     var count = this.segments.length;
 72     var index = 0;
 73     while (index < count && this.segments[index].end <= start) index++;
 74     // Insert new segment at position 'index'
 75     this.segments.splice(index, 0, new Segment(start, startValue, end, endValue, interpolator));
 76 }
 77 
 78 /**************************************************************************************************************/
 79 
 80 /*
 81 	Animation update method
 82 */
 83 SegmentedAnimation.prototype.update = function(now)
 84 {
 85     var t = Numeric.map01(now, this.startTime, this.startTime + this.duration);
 86     if (t >= 1)
 87     {
 88 		 // Set last value
 89 		var lastIndex = this.segments.length - 1;
 90 		this.valueSetter(this.segments[lastIndex].endValue);
 91 		this.stop();
 92     }
 93 	else
 94 	{
 95 		// Find current segment
 96 		var count = this.segments.length;
 97 		var index = 0;
 98 		while (index < count && this.segments[index].end < t) index++;
 99 		index = Math.min(index, count-1);
100 		
101 		// Remap t between segment bounds
102 		t = Numeric.map01(t, this.segments[index].start, this.segments[index].end);
103 		// Interpolate value
104 		var value = this.segments[index].interpolator(t, this.segments[index].startValue, this.segments[index].endValue);
105 		// Use value
106 		this.valueSetter(value);
107 	}
108 }
109 
110 /**************************************************************************************************************/
111 
112 return SegmentedAnimation;
113 
114 });
115