1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3 
  4  http://www.cocos2d-x.org
  5 
  6  Permission is hereby granted, free of charge, to any person obtaining a copy
  7  of this software and associated documentation files (the "Software"), to deal
  8  in the Software without restriction, including without limitation the rights
  9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10  copies of the Software, and to permit persons to whom the Software is
 11  furnished to do so, subject to the following conditions:
 12 
 13  The above copyright notice and this permission notice shall be included in
 14  all copies or substantial portions of the Software.
 15 
 16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22  THE SOFTWARE.
 23  ****************************************************************************/
 24 
 25 /**
 26  * Base class for ccs.ActionNode
 27  * @class
 28  * @extends ccs.Class
 29  */
 30 ccs.ActionNode = ccs.Class.extend({
 31     _currentFrameIndex: 0,
 32     _destFrameIndex: 0,
 33     _unitTime: 0,
 34     _actionTag: 0,
 35     _bject: null,
 36     _actionSpawn: null,
 37     _action: null,
 38     _frameArray: null,
 39     _frameArrayNum: 0,
 40     ctor: function () {
 41         this._currentFrameIndex = 0;
 42         this._destFrameIndex = 0;
 43         this._unitTime = 0.1;
 44         this._actionTag = 0;
 45         this._bject = null;
 46         this._actionSpawn = null;
 47         this._action = null;
 48         this._frameArray = [];
 49         this._frameArrayNum = ccs.FrameType.max;
 50         for (var i = 0; i < this._frameArrayNum; i++) {
 51             this._frameArray.push([]);
 52         }
 53     },
 54 
 55     /**
 56      *  Init properties with a json dictionary
 57      * @param {Object} dic
 58      * @param {Object} root
 59      */
 60     initWithDictionary: function (dic, root) {
 61         this.setActionTag(dic["ActionTag"]);
 62         var actionframelist = dic["actionframelist"];
 63         for (var i = 0; i < actionframelist.length; i++) {
 64             var actionFrameDic = actionframelist[i];
 65             var frameInex = actionFrameDic["frameid"];
 66             if (actionFrameDic["positionx"] !== undefined) {
 67                 var positionX = actionFrameDic["positionx"];
 68                 var positionY = actionFrameDic["positiony"];
 69                 var actionFrame = new ccs.ActionMoveFrame();
 70                 actionFrame.setFrameIndex(frameInex);
 71                 actionFrame.setPosition(cc.p(positionX, positionY));
 72                 var actionArray = this._frameArray[ccs.FrameType.move];
 73                 actionArray.push(actionFrame);
 74             }
 75 
 76             if (actionFrameDic["scalex"] !== undefined) {
 77                 var scaleX = actionFrameDic["scalex"];
 78                 var scaleY = actionFrameDic["scaley"];
 79                 var actionFrame = new ccs.ActionScaleFrame();
 80                 actionFrame.setFrameIndex(frameInex);
 81                 actionFrame.setScaleX(scaleX);
 82                 actionFrame.setScaleY(scaleY);
 83                 var actionArray = this._frameArray[ccs.FrameType.scale];
 84                 actionArray.push(actionFrame);
 85             }
 86 
 87             if (actionFrameDic["rotation"] !== undefined) {
 88                 var rotation = actionFrameDic["rotation"];
 89                 var actionFrame = new ccs.ActionRotationFrame();
 90                 actionFrame.setFrameIndex(frameInex);
 91                 actionFrame.setRotation(rotation);
 92                 var actionArray = this._frameArray[ccs.FrameType.rotate];
 93                 actionArray.push(actionFrame);
 94             }
 95 
 96             if (actionFrameDic["opacity"] !== undefined) {
 97                 var opacity = actionFrameDic["opacity"];
 98                 var actionFrame = new ccs.ActionFadeFrame();
 99                 actionFrame.setFrameIndex(frameInex);
100                 actionFrame.setOpacity(opacity);
101                 var actionArray = this._frameArray[ccs.FrameType.fade];
102                 actionArray.push(actionFrame);
103             }
104 
105             if (actionFrameDic["colorr"] !== undefined) {
106                 var colorR = actionFrameDic["colorr"];
107                 var colorG = actionFrameDic["colorg"];
108                 var colorB = actionFrameDic["colorb"];
109                 var actionFrame = new ccs.ActionTintFrame();
110                 actionFrame.setFrameIndex(frameInex);
111                 actionFrame.setColor(cc.c3b(colorR, colorG, colorB));
112                 var actionArray = this._frameArray[ccs.FrameType.tint];
113                 actionArray.push(actionFrame);
114             }
115             actionFrameDic = null;
116         }
117         this.initActionNodeFromRoot(root);
118     },
119 
120     initActionNodeFromRoot: function (root) {
121         if (root instanceof ccs.Widget) {
122             var widget = ccs.UIHelper.seekActionWidgetByActionTag(root, this.getActionTag());
123             if (widget) {
124                 this.setObject(widget);
125             }
126         }
127     },
128 
129     /**
130      * Sets the time interval of frame.
131      * @param {number} time
132      */
133     setUnitTime: function (time) {
134         this._unitTime = time;
135         this.refreshActionProperty();
136     },
137 
138     /**
139      * Gets the time interval of frame.
140      * @returns {number}
141      */
142     getUnitTime: function () {
143         return this._unitTime;
144     },
145 
146     /**
147      * Sets tag for ActionNode
148      * @param tag
149      */
150     setActionTag: function (tag) {
151         this._actionTag = tag;
152     },
153 
154     /**
155      * Gets tag for ActionNode
156      * @returns {number}
157      */
158     getActionTag: function () {
159         return this._actionTag;
160     },
161 
162     /**
163      * Sets node which will run a action.
164      * @param {Object} node
165      */
166     setObject: function (node) {
167         this._object = node;
168     },
169 
170     /**
171      * Gets node which will run a action.
172      * @returns {*}
173      */
174     getObject: function () {
175         return this._object;
176     },
177 
178     /**
179      * get actionNode
180      * @returns {cc.Node}
181      */
182     getActionNode: function () {
183         if (this._object instanceof cc.Node) {
184             return this._object;
185         }
186         else if (this._object instanceof ccs.Widget) {
187             return this._object;
188         }
189         return null;
190     },
191 
192     /**
193      * Insets a ActionFrame to ActionNode.
194      * @param {number} index
195      * @param {ccs.ActionFrame} frame
196      */
197     insertFrame: function (index, frame) {
198         if (frame == null) {
199             return;
200         }
201         var frameType = frame.getFrameType();
202         var array = this._frameArray[frameType];
203         array.splice(index, 0, frame);
204     },
205 
206     /**
207      * Pushs back a ActionFrame to ActionNode.
208      * @param {ccs.ActionFrame} frame
209      */
210     addFrame: function (frame) {
211         if (!frame) {
212             return;
213         }
214         var frameType = frame.getFrameType();
215         var array = this._frameArray[frameType];
216         array.push(frame);
217     },
218 
219     /**
220      * Remove a ActionFrame from ActionNode.
221      * @param {ccs.ActionFrame} frame
222      */
223     deleteFrame: function (frame) {
224         if (frame == null) {
225             return;
226         }
227         var frameType = frame.getFrameType();
228         var array = this._frameArray[frameType];
229         cc.ArrayRemoveObject(array, frame);
230     },
231 
232     /**
233      * Remove all ActionFrames from ActionNode.
234      */
235     clearAllFrame: function () {
236         for (var i = 0; i < this._frameArrayNum; i++) {
237             this._frameArray[i] = [];
238         }
239     },
240 
241     /**
242      * Refresh  property of action
243      * @returns {null}
244      */
245     refreshActionProperty: function () {
246         if (this._object == null) {
247             return null;
248         }
249         var locSpawnArray = [];
250         for (var i = 0; i < this._frameArrayNum; i++) {
251             var locArray = this._frameArray[i];
252             if (locArray.length <= 0) {
253                 continue;
254             }
255             var locSequenceArray = [];
256             for (var j = 0; j < locArray.length; j++) {
257                 var locFrame = locArray[j];
258                 if (j != 0) {
259                     var locSrcFrame = locArray[j - 1];
260                     var locDuration = (locFrame.getFrameIndex() - locSrcFrame.getFrameIndex()) * this.getUnitTime();
261                     var locAction = locFrame.getAction(locDuration);
262                     locSequenceArray.push(locAction);
263                 }
264             }
265             var locSequence = cc.Sequence.create(locSequenceArray);
266             if (locSequence != null) {
267                 locSpawnArray.push(locSequence);
268             }
269         }
270 
271         this._action = null;
272         this._actionSpawn = cc.Spawn.create(locSpawnArray);
273         return this._actionSpawn;
274     },
275 
276     /**
277      * Play the action.
278      * @param {Boolean} loop
279      * @param {cc.CallFunc} fun
280      */
281     playAction: function (fun) {
282         if (this._object == null || this._actionSpawn == null) {
283             return;
284         }
285         if(fun){
286             this._action = cc.Sequence.create(this._actionSpawn,fun);
287         }else{
288             this._action = cc.Sequence.create(this._actionSpawn);
289         }
290         this.runAction();
291     },
292 
293     /**
294      * Run action.
295      */
296     runAction: function () {
297         var node = this.getActionNode();
298         if (node != null && this._action != null) {
299             node.runAction(this._action);
300         }
301     },
302 
303     /**
304      * Stop action.
305      */
306     stopAction: function () {
307         var node = this.getActionNode();
308         if (node != null && this._action != null) {
309             if(!this._action.isDone())
310                 node.stopAction(this._action);
311         }
312     },
313 
314     /**
315      * Gets index of first ActionFrame.
316      * @returns {number}
317      */
318     getFirstFrameIndex: function () {
319         var locFrameindex = 99999;
320         var locIsFindFrame = false;
321         for (var i = 0; i < this._frameArrayNum; i++) {
322             var locArray = this._frameArray[i];
323             if (locArray.length <= 0) {
324                 continue;
325             }
326             locIsFindFrame = true;
327             var locFrame = locArray[0];
328             var locFrameIndex = locFrame.getFrameIndex();
329             locFrameindex = locFrameindex > locFrameIndex ? locFrameIndex : locFrameindex;
330         }
331         if (!locIsFindFrame) {
332             locFrameindex = 0;
333         }
334         return locFrameindex;
335     },
336 
337     /**
338      * Gets index of last ActionFrame.
339      * @returns {number}
340      */
341     getLastFrameIndex: function () {
342         var locFrameindex = -1;
343         var locIsFindFrame = false;
344         for (var i = 0; i < this._frameArrayNum; i++) {
345             var locArray = this._frameArray[i];
346             if (locArray.length <= 0) {
347                 continue;
348             }
349             locIsFindFrame = true;
350             var locFrame = locArray[locArray.length - 1];
351             var locFrameIndex = locFrame.getFrameIndex();
352             locFrameindex = locFrameindex < locFrameIndex ? locFrameIndex : locFrameindex;
353         }
354         if (!locIsFindFrame) {
355             locFrameindex = 0;
356         }
357         return locFrameindex;
358     },
359 
360     /**
361      * Updates action states to some time.
362      * @param time
363      * @returns {boolean}
364      */
365     updateActionToTimeLine: function (time) {
366         var locIsFindFrame = false;
367         var locUnitTime = this.getUnitTime();
368         for (var i = 0; i < this._frameArrayNum; i++) {
369             var locArray = this._frameArray[i];
370             if (locArray == null) {
371                 continue;
372             }
373 
374             for (var j = 0; j < locArray.length; j++) {
375                 var locFrame = locArray[j];
376                 if (locFrame.getFrameIndex() * locUnitTime == time) {
377                     this.easingToFrame(1.0, 1.0, locFrame);
378                     locIsFindFrame = true;
379                     break;
380                 }
381                 else if (locFrame.getFrameIndex() * locUnitTime > time) {
382                     if (j == 0) {
383                         this.easingToFrame(1.0, 1.0, locFrame);
384                         locIsFindFrame = false;
385                     }
386                     else {
387                         var locSrcFrame = locArray[j - 1];
388                         var locDuration = (locFrame.getFrameIndex() - locSrcFrame.getFrameIndex()) * locUnitTime;
389                         var locDelaytime = time - locSrcFrame.getFrameIndex() * locUnitTime;
390                         this.easingToFrame(locDuration, 1.0, locSrcFrame);
391                         this.easingToFrame(locDuration, locDelaytime / locDuration, locFrame);
392                         locIsFindFrame = true;
393                     }
394                     break;
395                 }
396             }
397         }
398         return locIsFindFrame;
399     },
400 
401     /**
402      * Easing to frame
403      * @param {number} duration
404      * @param {number} delayTime
405      * @param {ccs.ActionFrame} destFrame
406      */
407     easingToFrame: function (duration, delayTime, destFrame) {
408         var action = destFrame.getAction(duration);
409         var node = this.getActionNode();
410         if (action == null || node == null) {
411             return;
412         }
413         action.startWithTarget(node);
414         action.update(delayTime);
415     },
416 
417     isActionDoneOnce: function () {
418         if (this._action == null) {
419             return true;
420         }
421         return this._action.isDone();
422     }
423 });