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 var locAction = null; 270 if (j !== 0) { 271 var locSrcFrame = locArray[j - 1]; 272 var locDuration = (locFrame.frameIndex - locSrcFrame.frameIndex) * this.getUnitTime(); 273 locAction = locFrame.getAction(locDuration); 274 } 275 else { 276 locAction = locFrame.getAction(0); 277 } 278 if(locAction) 279 locSequenceArray.push(locAction); 280 } 281 if(locSequenceArray){ 282 var locSequence = cc.sequence(locSequenceArray); 283 if (locSequence !== null) 284 locSpawnArray.push(locSequence); 285 } 286 } 287 288 this._action = null; 289 this._actionSpawn = cc.spawn(locSpawnArray); 290 return this._actionSpawn; 291 }, 292 293 /** 294 * Plays ccs.ActionNode's action. 295 * @param {cc.CallFunc} fun 296 */ 297 playAction: function (fun) { 298 if (this._object === null || this._actionSpawn === null) 299 return; 300 if(fun) 301 this._action = cc.sequence(this._actionSpawn, fun); 302 else 303 this._action = cc.sequence(this._actionSpawn); 304 this._runAction(); 305 }, 306 307 _runAction: function () { 308 var node = this.getActionNode(); 309 if (node !== null && this._action !== null) 310 node.runAction(this._action); 311 }, 312 313 /** 314 * Stops action. 315 */ 316 stopAction: function () { 317 var node = this.getActionNode(); 318 if (node !== null && this._action !== null) { 319 if(!this._action.isDone()) 320 node.stopAction(this._action); 321 } 322 }, 323 324 /** 325 * Returns index of first ActionFrame. 326 * @returns {number} 327 */ 328 getFirstFrameIndex: function () { 329 var locFrameindex = 99999; 330 var bFindFrame = false, locFrameArray = this._frameArray; 331 for (var i = 0, len = this._frameArrayNum; i < len; i++) { 332 var locArray = locFrameArray[i]; 333 if (locArray.length <= 0) 334 continue; 335 bFindFrame = true; 336 var locFrameIndex = locArray[0].frameIndex; 337 locFrameindex = locFrameindex > locFrameIndex ? locFrameIndex : locFrameindex; 338 } 339 if (!bFindFrame) 340 locFrameindex = 0; 341 return locFrameindex; 342 }, 343 344 /** 345 * Returns the index of last ccs.ActionFrame. 346 * @returns {number} 347 */ 348 getLastFrameIndex: function () { 349 var locFrameindex = -1; 350 var locIsFindFrame = false ,locFrameArray = this._frameArray; 351 for (var i = 0, len = this._frameArrayNum; i < len; i++) { 352 var locArray = locFrameArray[i]; 353 if (locArray.length <= 0) 354 continue; 355 locIsFindFrame = true; 356 var locFrame = locArray[locArray.length - 1]; 357 var locFrameIndex = locFrame.frameIndex; 358 locFrameindex = locFrameindex < locFrameIndex ? locFrameIndex : locFrameindex; 359 } 360 if (!locIsFindFrame) 361 locFrameindex = 0; 362 return locFrameindex; 363 }, 364 365 /** 366 * Updates action states to some time. 367 * @param {Number} time 368 * @returns {boolean} 369 */ 370 updateActionToTimeLine: function (time) { 371 var locIsFindFrame = false; 372 var locUnitTime = this.getUnitTime(); 373 for (var i = 0; i < this._frameArrayNum; i++) { 374 var locArray = this._frameArray[i]; 375 if (locArray === null) 376 continue; 377 378 for (var j = 0; j < locArray.length; j++) { 379 var locFrame = locArray[j]; 380 if (locFrame.frameIndex * locUnitTime === time) { 381 this._easingToFrame(1.0, 1.0, locFrame); 382 locIsFindFrame = true; 383 break; 384 } else if (locFrame.frameIndex * locUnitTime > time) { 385 if (j === 0) { 386 this._easingToFrame(1.0, 1.0, locFrame); 387 locIsFindFrame = false; 388 } else { 389 var locSrcFrame = locArray[j - 1]; 390 var locDuration = (locFrame.frameIndex - locSrcFrame.frameIndex) * locUnitTime; 391 var locDelaytime = time - locSrcFrame.frameIndex * locUnitTime; 392 this._easingToFrame(locDuration, 1.0, locSrcFrame); 393 this._easingToFrame(locDuration, locDelaytime / locDuration, locFrame); 394 locIsFindFrame = true; 395 } 396 break; 397 } 398 } 399 } 400 return locIsFindFrame; 401 }, 402 403 _easingToFrame: function (duration, delayTime, destFrame) { 404 var action = destFrame.getAction(duration); 405 var node = this.getActionNode(); 406 if (action == null || node == null) 407 return; 408 action.startWithTarget(node); 409 action.update(delayTime); 410 }, 411 412 /** 413 * Returns if the action is done once time. 414 * @returns {Boolean} that if the action is done once time 415 */ 416 isActionDoneOnce: function () { 417 if (this._action === null) 418 return true; 419 return this._action.isDone(); 420 } 421 }); 422