1 /****************************************************************************
  2  Copyright (c) 2011-2012 cocos2d-x.org
  3  Copyright (c) 2013-2014 Chukong Technologies Inc.
  4 
  5  http://www.cocos2d-x.org
  6 
  7  Permission is hereby granted, free of charge, to any person obtaining a copy
  8  of this software and associated documentation files (the "Software"), to deal
  9  in the Software without restriction, including without limitation the rights
 10  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 11  copies of the Software, and to permit persons to whom the Software is
 12  furnished to do so, subject to the following conditions:
 13 
 14  The above copyright notice and this permission notice shall be included in
 15  all copies or substantial portions of the Software.
 16 
 17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 18  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 19  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 20  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 21  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 22  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 23  THE SOFTWARE.
 24  ****************************************************************************/
 25 
 26 
 27 //animation type
 28 /**
 29  * the animation just have one frame
 30  * @constant
 31  * @type {number}
 32  */
 33 ccs.ANIMATION_TYPE_SINGLE_FRAME = -4;
 34 /**
 35  * the animation isn't loop
 36  * @constant
 37  * @type {number}
 38  */
 39 ccs.ANIMATION_TYPE_NO_LOOP = -3;
 40 /**
 41  * the animation to loop from front
 42  * @constant
 43  * @type {number}
 44  */
 45 ccs.ANIMATION_TYPE_TO_LOOP_FRONT = -2;
 46 /**
 47  * the animation to loop from back
 48  * @constant
 49  * @type {number}
 50  */
 51 ccs.ANIMATION_TYPE_TO_LOOP_BACK = -1;
 52 /**
 53  * the animation loop from front
 54  * @constant
 55  * @type {number}
 56  */
 57 ccs.ANIMATION_TYPE_LOOP_FRONT = 0;
 58 /**
 59  * the animation loop from back
 60  * @constant
 61  * @type {number}
 62  */
 63 ccs.ANIMATION_TYPE_LOOP_BACK = 1;
 64 /**
 65  * the animation max
 66  * @constant
 67  * @type {number}
 68  */
 69 ccs.ANIMATION_TYPE_MAX = 2;
 70 
 71 /**
 72  * Base class for ccs.ProcessBase objects.
 73  * @class
 74  * @extends ccs.Class
 75  *
 76  * @property {Number}   currentFrameIndex   - <@readonly> The current frame's index
 77  * @property {Boolean}  paused              - <@readonly> Indicate whether the process is paused
 78  * @property {Boolean}  completed           - <@readonly> Indicate whether the process is done
 79  * @property {Number}   currentPercent      - <@readonly> The current percentage of the process
 80  * @property {Number}   rawDuration         - <@readonly> The duration
 81  * @property {Number}   loop                - <@readonly> The number of loop
 82  * @property {Number}   tweenEasing         - <@readonly> The tween easing
 83  * @property {Number}   animationInterval   - The animation internal
 84  * @property {Number}   processScale        - The process scale
 85  * @property {Boolean}  playing             - <@readonly> Indicate whether the process is playing
 86  */
 87 ccs.ProcessBase = ccs.Class.extend(/** @lends ccs.ProcessBase# */{
 88     _processScale: 1,
 89     _isComplete: true,
 90     _isPause: true,
 91     _isPlaying: false,
 92     _currentPercent: 0.0,
 93     _rawDuration: 0,
 94     _loopType: 0,
 95     _tweenEasing: 0,
 96     animationInternal: null,
 97     _currentFrame: 0,
 98     _durationTween: 0,
 99     _nextFrameIndex: 0,
100     _curFrameIndex: null,
101     _isLoopBack: false,
102 
103     ctor: function () {
104         this._processScale = 1;
105         this._isComplete = true;
106         this._isPause = true;
107         this._isPlaying = false;
108         this._currentFrame = 0;
109         this._currentPercent = 0.0;
110         this._durationTween = 0;
111         this._rawDuration = 0;
112         this._loopType = ccs.ANIMATION_TYPE_LOOP_BACK;
113         this._tweenEasing = ccs.TweenType.linear;
114         this.animationInternal = 1 / 60;
115         this._curFrameIndex = 0;
116         this._durationTween = 0;
117         this._isLoopBack = false;
118     },
119 
120     /**
121      * Pause the Process
122      */
123     pause: function () {
124         this._isPause = true;
125         this._isPlaying = false;
126     },
127 
128     /**
129      * Resume the Process
130      */
131     resume: function () {
132         this._isPause = false;
133         this._isPlaying = true;
134     },
135 
136     /**
137      * Stop the Process
138      */
139     stop: function () {
140         this._isComplete = true;
141         this._isPlaying = false;
142     },
143 
144     /**
145      * Play animation by animation name.
146      * @param {Number} durationTo The frames between two animation changing-over.
147      *         It's meaning is changing to this animation need how many frames
148      *         -1 : use the value from MovementData get from flash design panel
149      * @param {Number} durationTween  The frame count you want to play in the game.
150      *         if  _durationTween is 80, then the animation will played 80 frames in a loop
151      *         -1 : use the value from MovementData get from flash design panel
152      * @param {Number} loop Whether the animation is loop
153      *         loop < 0 : use the value from MovementData get from flash design panel
154      *         loop = 0 : this animation is not loop
155      *         loop > 0 : this animation is loop
156      * @param {Number} tweenEasing  Tween easing is used for calculate easing effect
157      *          TWEEN_EASING_MAX : use the value from MovementData get from flash design panel
158      *          -1 : fade out
159      *          0  : line
160      *          1  : fade in
161      *          2  : fade in and out
162      */
163     play: function (durationTo, durationTween, loop, tweenEasing) {
164         this._isComplete = false;
165         this._isPause = false;
166         this._isPlaying = true;
167         this._currentFrame = 0;
168         /*
169          *  Set m_iTotalFrames to durationTo, it is used for change tween between two animation.
170          *  When changing end, m_iTotalFrames will be set to _durationTween
171          */
172         this._nextFrameIndex = durationTo;
173         this._tweenEasing = tweenEasing;
174     },
175 
176     update: function (dt) {
177         if (this._isComplete || this._isPause)
178             return;
179 
180         /*
181          *  Fileter the m_iDuration <=0 and dt >1
182          *  If dt>1, generally speaking  the reason is the device is stuck.
183          */
184         if (this._rawDuration <= 0 || dt > 1)
185             return;
186 
187         var locNextFrameIndex = this._nextFrameIndex === undefined ? 0 : this._nextFrameIndex;
188         var locCurrentFrame = this._currentFrame;
189         if (locNextFrameIndex <= 0) {
190             this._currentPercent = 1;
191             locCurrentFrame = 0;
192         } else {
193             /*
194              *  update currentFrame, every update add the frame passed.
195              *  dt/this.animationInternal determine it is not a frame animation. If frame speed changed, it will not make our
196              *  animation speed slower or quicker.
197              */
198             locCurrentFrame += this._processScale * (dt / this.animationInternal);
199             this._currentPercent = locCurrentFrame / locNextFrameIndex;
200 
201             /*
202              *	if currentFrame is bigger or equal than this._nextFrameIndex, then reduce it util currentFrame is
203              *  smaller than this._nextFrameIndex
204              */
205             locCurrentFrame = ccs.fmodf(locCurrentFrame, locNextFrameIndex);
206         }
207         this._currentFrame = locCurrentFrame;
208         this.updateHandler();
209     },
210 
211     /**
212      * goto frame
213      * @param {Number} frameIndex
214      */
215     gotoFrame: function (frameIndex) {
216         var locLoopType = this._loopType;
217         if (locLoopType == ccs.ANIMATION_TYPE_NO_LOOP)
218             locLoopType = ccs.ANIMATION_TYPE_MAX;
219         else if (locLoopType == ccs.ANIMATION_TYPE_TO_LOOP_FRONT)
220             locLoopType = ccs.ANIMATION_TYPE_LOOP_FRONT;
221         this._loopType = locLoopType;
222         this._curFrameIndex = frameIndex;
223         this._nextFrameIndex = this._durationTween;
224     },
225 
226     /**
227      * get currentFrameIndex
228      * @return {Number}
229      */
230     getCurrentFrameIndex: function () {
231         this._curFrameIndex = (this._rawDuration - 1) * this._currentPercent;
232         return this._curFrameIndex;
233     },
234 
235     /**
236      * update will call this handler, you can handle your logic here
237      */
238     updateHandler: function () {
239         //override
240     },
241 
242     /**
243      * whether the animation is pause
244      * @returns {boolean}
245      */
246     isPause: function () {
247         return this._isPause;
248     },
249 
250     /**
251      * whether the animation is complete
252      * @returns {boolean}
253      */
254     isComplete: function () {
255         return this._isComplete;
256     },
257 
258     /**
259      * current percent getter
260      * @returns {number}
261      */
262     getCurrentPercent: function () {
263         return this._currentPercent;
264     },
265 
266     /**
267      * rawDuration getter
268      * @returns {number}
269      */
270     getRawDuration: function () {
271         return this._rawDuration;
272     },
273 
274     /**
275      *  loop type getter
276      * @returns {number}
277      */
278     getLoop: function () {
279         return this._loopType;
280     },
281 
282     /**
283      * tween easing getter
284      * @returns {number}
285      */
286     getTweenEasing: function () {
287         return this._tweenEasing;
288     },
289 
290     /**
291      * animationInternal getter
292      * @returns {number}
293      */
294     getAnimationInternal: function () {
295         return this.animationInternal;
296     },
297 
298     /**
299      * animationInternal setter
300      * @param animationInternal
301      */
302     setAnimationInternal: function (animationInternal) {
303         this.animationInternal = animationInternal;
304     },
305 
306     /**
307      * process scale getter
308      * @returns {number}
309      */
310     getProcessScale: function () {
311         return this._processScale;
312     },
313 
314     /**
315      * process scale setter
316      * @param processScale
317      */
318     setProcessScale: function (processScale) {
319         this._processScale = processScale;
320     },
321 
322     /**
323      * whether the animation is playing
324      * @returns {boolean}
325      */
326     isPlaying: function () {
327         return this._isPlaying;
328     }
329 });
330 
331 var _p = ccs.ProcessBase.prototype;
332 
333 // Extended properties
334 /** @expose */
335 _p.currentFrameIndex;
336 cc.defineGetterSetter(_p, "currentFrameIndex", _p.getCurrentFrameIndex);
337 /** @expose */
338 _p.paused;
339 cc.defineGetterSetter(_p, "paused", _p.isPause);
340 /** @expose */
341 _p.completed;
342 cc.defineGetterSetter(_p, "completed", _p.isComplete);
343 /** @expose */
344 _p.currentPercent;
345 cc.defineGetterSetter(_p, "currentPercent", _p.getCurrentPercent);
346 /** @expose */
347 _p.rawDuration;
348 cc.defineGetterSetter(_p, "rawDuration", _p.getRawDuration);
349 /** @expose */
350 _p.loop;
351 cc.defineGetterSetter(_p, "loop", _p.getLoop);
352 /** @expose */
353 _p.tweenEasing;
354 cc.defineGetterSetter(_p, "tweenEasing", _p.getTweenEasing);
355 /** @expose */
356 _p.playing;
357 cc.defineGetterSetter(_p, "playing", _p.isPlaying);
358 
359 _p = null;
360