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 * The Cocostudio's action node, it contains action target, action frame list and current frame index. it can be play action by calling playAciton. 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 _object: null, 37 _actionSpawn: null, 38 _action: null, 39 _frameArray: null, 40 _frameArrayNum: 0, 41 42 /** 43 * Construction of ccs.ActionNode 44 */ 45 ctor: function () { 46 this._currentFrameIndex = 0; 47 this._destFrameIndex = 0; 48 this._unitTime = 0.1; 49 this._actionTag = 0; 50 this._object = null; 51 this._actionSpawn = null; 52 this._action = null; 53 this._frameArray = []; 54 this._frameArrayNum = ccs.FRAME_TYPE_MAX; 55 for (var i = 0; i < this._frameArrayNum; i++) 56 this._frameArray.push([]); 57 }, 58 59 /** 60 * Init properties with a json dictionary 61 * @param {Object} dic 62 * @param {Object} root 63 */ 64 initWithDictionary: function (dic, root) { 65 this.setActionTag(dic["ActionTag"]); 66 var actionFrameList = dic["actionframelist"]; 67 for (var i = 0; i < actionFrameList.length; i++) { 68 var actionFrameDic = actionFrameList[i]; 69 var frameIndex = actionFrameDic["frameid"]; 70 var frameTweenType = actionFrameDic["tweenType"]; 71 if(frameTweenType == null) 72 frameTweenType = 0; 73 var frameTweenParameterNum = actionFrameDic["tweenParameter"]; 74 75 var frameTweenParameter = []; 76 for (var j = 0; j < frameTweenParameterNum; j++){ 77 var value = actionFrameDic["tweenParameter"][j]; 78 frameTweenParameter.push(value); 79 } 80 81 var actionFrame, actionArray; 82 if (actionFrameDic["positionx"] !== undefined) { 83 var positionX = actionFrameDic["positionx"]; 84 var positionY = actionFrameDic["positiony"]; 85 actionFrame = new ccs.ActionMoveFrame(); 86 actionFrame.frameIndex = frameIndex; 87 actionFrame.setEasingType(frameTweenType); 88 actionFrame.setEasingParameter(frameTweenParameter); 89 actionFrame.setPosition(positionX, positionY); 90 actionArray = this._frameArray[ccs.FRAME_TYPE_MOVE]; 91 actionArray.push(actionFrame); 92 } 93 94 if (actionFrameDic["scalex"] !== undefined) { 95 var scaleX = actionFrameDic["scalex"]; 96 var scaleY = actionFrameDic["scaley"]; 97 actionFrame = new ccs.ActionScaleFrame(); 98 actionFrame.frameIndex = frameIndex; 99 actionFrame.setEasingType(frameTweenType); 100 actionFrame.setEasingParameter(frameTweenParameter); 101 actionFrame.setScaleX(scaleX); 102 actionFrame.setScaleY(scaleY); 103 actionArray = this._frameArray[ccs.FRAME_TYPE_SCALE]; 104 actionArray.push(actionFrame); 105 } 106 107 if (actionFrameDic["rotation"] !== undefined) { 108 var rotation = actionFrameDic["rotation"]; 109 actionFrame = new ccs.ActionRotationFrame(); 110 actionFrame.frameIndex = frameIndex; 111 actionFrame.setEasingType(frameTweenType); 112 actionFrame.setEasingParameter(frameTweenParameter); 113 actionFrame.setRotation(rotation); 114 actionArray = this._frameArray[ccs.FRAME_TYPE_ROTATE]; 115 actionArray.push(actionFrame); 116 } 117 118 if (actionFrameDic["opacity"] !== undefined) { 119 var opacity = actionFrameDic["opacity"]; 120 actionFrame = new ccs.ActionFadeFrame(); 121 actionFrame.frameIndex = frameIndex; 122 actionFrame.setEasingType(frameTweenType); 123 actionFrame.setEasingParameter(frameTweenParameter); 124 actionFrame.setOpacity(opacity); 125 actionArray = this._frameArray[ccs.FRAME_TYPE_FADE]; 126 actionArray.push(actionFrame); 127 } 128 129 if (actionFrameDic["colorr"] !== undefined) { 130 var colorR = actionFrameDic["colorr"]; 131 var colorG = actionFrameDic["colorg"]; 132 var colorB = actionFrameDic["colorb"]; 133 actionFrame = new ccs.ActionTintFrame(); 134 actionFrame.frameIndex = frameIndex; 135 actionFrame.setEasingType(frameTweenType); 136 actionFrame.setEasingParameter(frameTweenParameter); 137 actionFrame.setColor(cc.color(colorR, colorG, colorB)); 138 actionArray = this._frameArray[ccs.FRAME_TYPE_TINT]; 139 actionArray.push(actionFrame); 140 } 141 actionFrameDic = null; 142 } 143 this._initActionNodeFromRoot(root); 144 }, 145 146 _initActionNodeFromRoot: function (root) { 147 if (root instanceof ccui.Widget) { 148 var widget = ccui.helper.seekActionWidgetByActionTag(root, this.getActionTag()); 149 if (widget) 150 this.setObject(widget); 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 * Returns the time interval of frame. 165 * @returns {number} 166 */ 167 getUnitTime: function () { 168 return this._unitTime; 169 }, 170 171 /** 172 * Sets tag to ccs.ActionNode 173 * @param {Number} tag 174 */ 175 setActionTag: function (tag) { 176 this._actionTag = tag; 177 }, 178 179 /** 180 * Returns the tag of ccs.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 * Returns node which will run a action. 197 * @returns {*} 198 */ 199 getObject: function () { 200 return this._object; 201 }, 202 203 /** 204 * Returns the target node of ccs.ActionNode 205 * @returns {cc.Node} 206 */ 207 getActionNode: function () { 208 if (this._object instanceof cc.Node) 209 return this._object; 210 return null; 211 }, 212 213 /** 214 * Inserts an ActionFrame to ccs.ActionNode. 215 * @param {number} index 216 * @param {ccs.ActionFrame} frame 217 */ 218 insertFrame: function (index, frame) { 219 if (frame == null) 220 return; 221 var frameType = frame.frameType; 222 var array = this._frameArray[frameType]; 223 array.splice(index, 0, frame); 224 }, 225 226 /** 227 * Pushes back an ActionFrame to ccs.ActionNode. 228 * @param {ccs.ActionFrame} frame 229 */ 230 addFrame: function (frame) { 231 if (!frame) 232 return; 233 var frameType = frame.frameType; 234 var array = this._frameArray[frameType]; 235 array.push(frame); 236 }, 237 238 /** 239 * Removes an ActionFrame from ccs.ActionNode. 240 * @param {ccs.ActionFrame} frame 241 */ 242 deleteFrame: function (frame) { 243 if (frame == null) 244 return; 245 var frameType = frame.frameType; 246 var array = this._frameArray[frameType]; 247 cc.arrayRemoveObject(array, frame); 248 }, 249 250 /** 251 * Removes all ActionFrames from ccs.ActionNode. 252 */ 253 clearAllFrame: function () { 254 for (var i = 0; i < this._frameArrayNum; i++) 255 this._frameArray[i].length = 0; 256 }, 257 258 _refreshActionProperty: function () { 259 if (this._object == null) 260 return null; 261 var locSpawnArray = []; 262 for (var i = 0; i < this._frameArrayNum; i++) { 263 var locArray = this._frameArray[i]; 264 if (locArray.length <= 0) 265 continue; 266 var locSequenceArray = []; 267 for (var j = 0; j < locArray.length; j++) { 268 var locFrame = locArray[j]; 269 if (j != 0) { 270 var locSrcFrame = locArray[j - 1]; 271 var locDuration = (locFrame.frameIndex - locSrcFrame.frameIndex) * this.getUnitTime(); 272 var locAction = locFrame.getAction(locDuration); 273 if(locAction) 274 locSequenceArray.push(locAction); 275 } 276 } 277 if(locSequenceArray){ 278 var locSequence = cc.sequence(locSequenceArray); 279 if (locSequence != null) 280 locSpawnArray.push(locSequence); 281 } 282 } 283 284 this._action = null; 285 this._actionSpawn = cc.spawn(locSpawnArray); 286 return this._actionSpawn; 287 }, 288 289 /** 290 * Plays ccs.ActionNode's action. 291 * @param {cc.CallFunc} fun 292 */ 293 playAction: function (fun) { 294 if (this._object == null || this._actionSpawn == null) 295 return; 296 if(fun) 297 this._action = cc.sequence(this._actionSpawn, fun); 298 else 299 this._action = cc.sequence(this._actionSpawn); 300 this._runAction(); 301 }, 302 303 _runAction: function () { 304 var node = this.getActionNode(); 305 if (node != null && this._action != null) 306 node.runAction(this._action); 307 }, 308 309 /** 310 * Stops action. 311 */ 312 stopAction: function () { 313 var node = this.getActionNode(); 314 if (node != null && this._action != null) { 315 if(!this._action.isDone()) 316 node.stopAction(this._action); 317 } 318 }, 319 320 /** 321 * Returns index of first ActionFrame. 322 * @returns {number} 323 */ 324 getFirstFrameIndex: function () { 325 var locFrameindex = 99999; 326 var bFindFrame = false, locFrameArray = this._frameArray; 327 for (var i = 0, len = this._frameArrayNum; i < len; i++) { 328 var locArray = locFrameArray[i]; 329 if (locArray.length <= 0) 330 continue; 331 bFindFrame = true; 332 var locFrameIndex = locArray[0].frameIndex; 333 locFrameindex = locFrameindex > locFrameIndex ? locFrameIndex : locFrameindex; 334 } 335 if (!bFindFrame) 336 locFrameindex = 0; 337 return locFrameindex; 338 }, 339 340 /** 341 * Returns the index of last ccs.ActionFrame. 342 * @returns {number} 343 */ 344 getLastFrameIndex: function () { 345 var locFrameindex = -1; 346 var locIsFindFrame = false ,locFrameArray = this._frameArray; 347 for (var i = 0, len = this._frameArrayNum; i < len; i++) { 348 var locArray = locFrameArray[i]; 349 if (locArray.length <= 0) 350 continue; 351 locIsFindFrame = true; 352 var locFrame = locArray[locArray.length - 1]; 353 var locFrameIndex = locFrame.frameIndex; 354 locFrameindex = locFrameindex < locFrameIndex ? locFrameIndex : locFrameindex; 355 } 356 if (!locIsFindFrame) 357 locFrameindex = 0; 358 return locFrameindex; 359 }, 360 361 /** 362 * Updates action states to some time. 363 * @param {Number} time 364 * @returns {boolean} 365 */ 366 updateActionToTimeLine: function (time) { 367 var locIsFindFrame = false; 368 var locUnitTime = this.getUnitTime(); 369 for (var i = 0; i < this._frameArrayNum; i++) { 370 var locArray = this._frameArray[i]; 371 if (locArray == null) 372 continue; 373 374 for (var j = 0; j < locArray.length; j++) { 375 var locFrame = locArray[j]; 376 if (locFrame.frameIndex * locUnitTime == time) { 377 this._easingToFrame(1.0, 1.0, locFrame); 378 locIsFindFrame = true; 379 break; 380 } else if (locFrame.frameIndex * locUnitTime > time) { 381 if (j == 0) { 382 this._easingToFrame(1.0, 1.0, locFrame); 383 locIsFindFrame = false; 384 } else { 385 var locSrcFrame = locArray[j - 1]; 386 var locDuration = (locFrame.frameIndex - locSrcFrame.frameIndex) * locUnitTime; 387 var locDelaytime = time - locSrcFrame.frameIndex * locUnitTime; 388 this._easingToFrame(locDuration, 1.0, locSrcFrame); 389 this._easingToFrame(locDuration, locDelaytime / locDuration, locFrame); 390 locIsFindFrame = true; 391 } 392 break; 393 } 394 } 395 } 396 return locIsFindFrame; 397 }, 398 399 _easingToFrame: function (duration, delayTime, destFrame) { 400 var action = destFrame.getAction(duration); 401 var node = this.getActionNode(); 402 if (action == null || node == null) 403 return; 404 action.startWithTarget(node); 405 action.update(delayTime); 406 }, 407 408 /** 409 * Returns if the action is done once time. 410 * @returns {Boolean} that if the action is done once time 411 */ 412 isActionDoneOnce: function () { 413 if (this._action == null) 414 return true; 415 return this._action.isDone(); 416 } 417 });