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  * Base class for ccs.ActionNode
 28  * @class
 29  * @extends ccs.Class
 30  */
 31 ccs.ActionNode = ccs.Class.extend(/** @lends ccs.ActionNode# */{
 32     _currentFrameIndex: 0,
 33     _destFrameIndex: 0,
 34     _unitTime: 0,
 35     _actionTag: 0,
 36     _bject: null,
 37     _actionSpawn: null,
 38     _action: null,
 39     _frameArray: null,
 40     _frameArrayNum: 0,
 41     ctor: function () {
 42         this._currentFrameIndex = 0;
 43         this._destFrameIndex = 0;
 44         this._unitTime = 0.1;
 45         this._actionTag = 0;
 46         this._bject = null;
 47         this._actionSpawn = null;
 48         this._action = null;
 49         this._frameArray = [];
 50         this._frameArrayNum = ccs.FRAME_TYPE_MAX;
 51         for (var i = 0; i < this._frameArrayNum; i++) {
 52             this._frameArray.push([]);
 53         }
 54     },
 55 
 56     /**
 57      *  Init properties with a json dictionary
 58      * @param {Object} dic
 59      * @param {Object} root
 60      */
 61     initWithDictionary: function (dic, root) {
 62         this.setActionTag(dic["ActionTag"]);
 63         var actionframelist = dic["actionframelist"];
 64         for (var i = 0; i < actionframelist.length; i++) {
 65             var actionFrameDic = actionframelist[i];
 66             var frameInex = actionFrameDic["frameid"];
 67             var frameTweenType = actionFrameDic["tweenType"];
 68             var frameTweenParameterNum = actionFrameDic["tweenParameter"];
 69 
 70             var frameTweenParameter = [];
 71             for (var j = 0; j < frameTweenParameterNum; j++){
 72                 var value = actionFrameDic["tweenParameter"][j];
 73                 frameTweenParameter.push(value);
 74             }
 75 
 76             if (actionFrameDic["positionx"] !== undefined) {
 77                 var positionX = actionFrameDic["positionx"];
 78                 var positionY = actionFrameDic["positiony"];
 79                 var actionFrame = new ccs.ActionMoveFrame();
 80 //                actionFrame.easingType = frameTweenType;
 81 //                actionFrame.frameIndex = frameInex;
 82                 actionFrame.setEasingType(frameTweenType);
 83                 actionFrame.setEasingParameter(frameTweenParameter);
 84                 actionFrame.setPosition(positionX, positionY);
 85                 var actionArray = this._frameArray[ccs.FRAME_TYPE_MOVE];
 86                 actionArray.push(actionFrame);
 87             }
 88 
 89             if (actionFrameDic["scalex"] !== undefined) {
 90                 var scaleX = actionFrameDic["scalex"];
 91                 var scaleY = actionFrameDic["scaley"];
 92                 var actionFrame = new ccs.ActionScaleFrame();
 93 //                actionFrame.easingType = frameTweenType;
 94 //                actionFrame.frameIndex = frameInex;
 95                 actionFrame.setEasingType(frameTweenType);
 96                 actionFrame.setEasingParameter(frameTweenParameter);
 97                 actionFrame.setScaleX(scaleX);
 98                 actionFrame.setScaleY(scaleY);
 99                 var actionArray = this._frameArray[ccs.FRAME_TYPE_SCALE];
100                 actionArray.push(actionFrame);
101             }
102 
103             if (actionFrameDic["rotation"] !== undefined) {
104                 var rotation = actionFrameDic["rotation"];
105                 var actionFrame = new ccs.ActionRotationFrame();
106 //                actionFrame.easingType = frameTweenType;
107 //                actionFrame.frameIndex = frameInex;
108                 actionFrame.setEasingType(frameTweenType);
109                 actionFrame.setEasingParameter(frameTweenParameter);
110                 actionFrame.setRotation(rotation);
111                 var actionArray = this._frameArray[ccs.FRAME_TYPE_ROTATE];
112                 actionArray.push(actionFrame);
113             }
114 
115             if (actionFrameDic["opacity"] !== undefined) {
116                 var opacity = actionFrameDic["opacity"];
117                 var actionFrame = new ccs.ActionFadeFrame();
118 //                actionFrame.easingType = frameTweenType;
119 //                actionFrame.frameIndex = frameInex;
120                 actionFrame.setEasingType(frameTweenType);
121                 actionFrame.setEasingParameter(frameTweenParameter);
122                 actionFrame.setOpacity(opacity);
123                 var actionArray = this._frameArray[ccs.FRAME_TYPE_FADE];
124                 actionArray.push(actionFrame);
125             }
126 
127             if (actionFrameDic["colorr"] !== undefined) {
128                 var colorR = actionFrameDic["colorr"];
129                 var colorG = actionFrameDic["colorg"];
130                 var colorB = actionFrameDic["colorb"];
131                 var actionFrame = new ccs.ActionTintFrame();
132 //                actionFrame.easingType = frameTweenType;
133 //                actionFrame.frameIndex = frameInex;
134                 actionFrame.setEasingType(frameTweenType);
135                 actionFrame.setEasingParameter(frameTweenParameter);
136                 actionFrame.setColor(cc.color(colorR, colorG, colorB));
137                 var actionArray = this._frameArray[ccs.FRAME_TYPE_TINT];
138                 actionArray.push(actionFrame);
139             }
140             actionFrameDic = null;
141         }
142         this.initActionNodeFromRoot(root);
143     },
144 
145     initActionNodeFromRoot: function (root) {
146         if (root instanceof ccui.Widget) {
147             var widget = ccui.helper.seekActionWidgetByActionTag(root, this.getActionTag());
148             if (widget) {
149                 this.setObject(widget);
150             }
151         }
152     },
153 
154     /**
155      * Sets the time interval of frame.
156      * @param {number} time
157      */
158     setUnitTime: function (time) {
159         this._unitTime = time;
160         this.refreshActionProperty();
161     },
162 
163     /**
164      * Gets the time interval of frame.
165      * @returns {number}
166      */
167     getUnitTime: function () {
168         return this._unitTime;
169     },
170 
171     /**
172      * Sets tag for ActionNode
173      * @param tag
174      */
175     setActionTag: function (tag) {
176         this._actionTag = tag;
177     },
178 
179     /**
180      * Gets tag for ActionNode
181      * @returns {number}
182      */
183     getActionTag: function () {
184         return this._actionTag;
185     },
186 
187     /**
188      * Sets node which will run a action.
189      * @param {Object} node
190      */
191     setObject: function (node) {
192         this._object = node;
193     },
194 
195     /**
196      * Gets node which will run a action.
197      * @returns {*}
198      */
199     getObject: function () {
200         return this._object;
201     },
202 
203     /**
204      * get actionNode
205      * @returns {cc.Node}
206      */
207     getActionNode: function () {
208         if (this._object instanceof cc.Node) {
209             return this._object;
210         }
211         else if (this._object instanceof ccui.Widget) {
212             return this._object;
213         }
214         return null;
215     },
216 
217     /**
218      * Insets a ActionFrame to ActionNode.
219      * @param {number} index
220      * @param {ccs.ActionFrame} frame
221      */
222     insertFrame: function (index, frame) {
223         if (frame == null) {
224             return;
225         }
226         var frameType = frame.frameType;
227         var array = this._frameArray[frameType];
228         array.splice(index, 0, frame);
229     },
230 
231     /**
232      * Pushs back a ActionFrame to ActionNode.
233      * @param {ccs.ActionFrame} frame
234      */
235     addFrame: function (frame) {
236         if (!frame) {
237             return;
238         }
239         var frameType = frame.frameType;
240         var array = this._frameArray[frameType];
241         array.push(frame);
242     },
243 
244     /**
245      * Remove a ActionFrame from ActionNode.
246      * @param {ccs.ActionFrame} frame
247      */
248     deleteFrame: function (frame) {
249         if (frame == null) {
250             return;
251         }
252         var frameType = frame.frameType;
253         var array = this._frameArray[frameType];
254         cc.arrayRemoveObject(array, frame);
255     },
256 
257     /**
258      * Remove all ActionFrames from ActionNode.
259      */
260     clearAllFrame: function () {
261         for (var i = 0; i < this._frameArrayNum; i++) {
262             this._frameArray[i] = [];
263         }
264     },
265 
266     /**
267      * Refresh  property of action
268      * @returns {null}
269      */
270     refreshActionProperty: function () {
271         if (this._object == null) {
272             return null;
273         }
274         var locSpawnArray = [];
275         for (var i = 0; i < this._frameArrayNum; i++) {
276             var locArray = this._frameArray[i];
277             if (locArray.length <= 0) {
278                 continue;
279             }
280             var locSequenceArray = [];
281             for (var j = 0; j < locArray.length; j++) {
282                 var locFrame = locArray[j];
283                 if (j != 0) {
284                     var locSrcFrame = locArray[j - 1];
285                     var locDuration = (locFrame.frameIndex - locSrcFrame.frameIndex) * this.getUnitTime();
286                     var locAction = locFrame.getAction(locDuration);
287                     if(locAction){
288                         locSequenceArray.push(locAction);
289                     }
290                 }
291             }
292             if(locSequenceArray){
293                 var locSequence = cc.Sequence.create(locSequenceArray);
294                 if (locSequence != null) {
295                     locSpawnArray.push(locSequence);
296                 }
297             }
298         }
299 
300         this._action = null;
301         this._actionSpawn = cc.Spawn.create(locSpawnArray);
302         return this._actionSpawn;
303     },
304 
305     /**
306      * Play the action.
307      * @param {Boolean} loop
308      * @param {cc.CallFunc} fun
309      */
310     playAction: function (fun) {
311         if (this._object == null || this._actionSpawn == null) {
312             return;
313         }
314         if(fun){
315             this._action = cc.Sequence.create(this._actionSpawn,fun);
316         }else{
317             this._action = cc.Sequence.create(this._actionSpawn);
318         }
319         this.runAction();
320     },
321 
322     /**
323      * Run action.
324      */
325     runAction: function () {
326         var node = this.getActionNode();
327         if (node != null && this._action != null) {
328             node.runAction(this._action);
329         }
330     },
331 
332     /**
333      * Stop action.
334      */
335     stopAction: function () {
336         var node = this.getActionNode();
337         if (node != null && this._action != null) {
338             if(!this._action.isDone())
339                 node.stopAction(this._action);
340         }
341     },
342 
343     /**
344      * Gets index of first ActionFrame.
345      * @returns {number}
346      */
347     getFirstFrameIndex: function () {
348         var locFrameindex = 99999;
349         var locIsFindFrame = false;
350         for (var i = 0; i < this._frameArrayNum; i++) {
351             var locArray = this._frameArray[i];
352             if (locArray.length <= 0) {
353                 continue;
354             }
355             locIsFindFrame = true;
356             var locFrame = locArray[0];
357             var locFrameIndex = locFrame.frameIndex;
358             locFrameindex = locFrameindex > locFrameIndex ? locFrameIndex : locFrameindex;
359         }
360         if (!locIsFindFrame) {
361             locFrameindex = 0;
362         }
363         return locFrameindex;
364     },
365 
366     /**
367      * Gets index of last ActionFrame.
368      * @returns {number}
369      */
370     getLastFrameIndex: function () {
371         var locFrameindex = -1;
372         var locIsFindFrame = false;
373         for (var i = 0; i < this._frameArrayNum; i++) {
374             var locArray = this._frameArray[i];
375             if (locArray.length <= 0) {
376                 continue;
377             }
378             locIsFindFrame = true;
379             var locFrame = locArray[locArray.length - 1];
380             var locFrameIndex = locFrame.frameIndex;
381             locFrameindex = locFrameindex < locFrameIndex ? locFrameIndex : locFrameindex;
382         }
383         if (!locIsFindFrame) {
384             locFrameindex = 0;
385         }
386         return locFrameindex;
387     },
388 
389     /**
390      * Updates action states to some time.
391      * @param time
392      * @returns {boolean}
393      */
394     updateActionToTimeLine: function (time) {
395         var locIsFindFrame = false;
396         var locUnitTime = this.getUnitTime();
397         for (var i = 0; i < this._frameArrayNum; i++) {
398             var locArray = this._frameArray[i];
399             if (locArray == null) {
400                 continue;
401             }
402 
403             for (var j = 0; j < locArray.length; j++) {
404                 var locFrame = locArray[j];
405                 if (locFrame.frameIndex * locUnitTime == time) {
406                     this.easingToFrame(1.0, 1.0, locFrame);
407                     locIsFindFrame = true;
408                     break;
409                 }
410                 else if (locFrame.frameIndex * locUnitTime > time) {
411                     if (j == 0) {
412                         this.easingToFrame(1.0, 1.0, locFrame);
413                         locIsFindFrame = false;
414                     }
415                     else {
416                         var locSrcFrame = locArray[j - 1];
417                         var locDuration = (locFrame.frameIndex - locSrcFrame.frameIndex) * locUnitTime;
418                         var locDelaytime = time - locSrcFrame.frameIndex * locUnitTime;
419                         this.easingToFrame(locDuration, 1.0, locSrcFrame);
420                         this.easingToFrame(locDuration, locDelaytime / locDuration, locFrame);
421                         locIsFindFrame = true;
422                     }
423                     break;
424                 }
425             }
426         }
427         return locIsFindFrame;
428     },
429 
430     /**
431      * Easing to frame
432      * @param {number} duration
433      * @param {number} delayTime
434      * @param {ccs.ActionFrame} destFrame
435      */
436     easingToFrame: function (duration, delayTime, destFrame) {
437         var action = destFrame.getAction(duration);
438         var node = this.getActionNode();
439         if (action == null || node == null) {
440             return;
441         }
442         action.startWithTarget(node);
443         action.update(delayTime);
444     },
445 
446     isActionDoneOnce: function () {
447         if (this._action == null) {
448             return true;
449         }
450         return this._action.isDone();
451     }
452 });