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