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 display manager for CocoStudio Armature bone. 28 * @Class ccs.DisplayManager 29 * @extend cc.Class 30 */ 31 ccs.DisplayManager = ccs.Class.extend(/** @lends ccs.DisplayManager */{ 32 _decoDisplayList:null, 33 _currentDecoDisplay:null, 34 _displayRenderNode:null, 35 _displayIndex: null, 36 _forceChangeDisplay:false, 37 _bone:null, 38 _visible:true, 39 _displayType: null, 40 41 /** 42 * Construction of ccs.DisplayManager. 43 */ 44 ctor:function () { 45 this._decoDisplayList = []; 46 this._currentDecoDisplay = null; 47 this._displayRenderNode = null; 48 this._displayIndex = null; 49 this._forceChangeDisplay = false; 50 this._bone = null; 51 this._visible = true; 52 this._displayType = ccs.DISPLAY_TYPE_MAX; 53 }, 54 55 /** 56 * Initializes a ccs.DisplayManager. 57 * @param bone 58 * @returns {boolean} 59 */ 60 init:function (bone) { 61 this._bone = bone; 62 this.initDisplayList(bone.getBoneData()); 63 return true; 64 }, 65 66 /** 67 * <p> 68 * Add display and use _DisplayData init the display. <br/> 69 * If index already have a display, then replace it. <br/> 70 * If index is current display index, then also change display to _index <br/> 71 * </p> 72 * @param {ccs.DisplayData|cc.Node} display it include the display information, like DisplayType. If you want to create a sprite display, then create a SpriteDisplayData param 73 * @param {Number} index the index of the display you want to replace or add to. -1 : append display from back 74 */ 75 addDisplay: function (display, index) { 76 var decoDisplay, locDisplayList = this._decoDisplayList; 77 if( (index >= 0) && (index < locDisplayList.length) ) 78 decoDisplay = locDisplayList[index]; 79 else{ 80 decoDisplay = ccs.DecorativeDisplay.create(); 81 locDisplayList.push(decoDisplay); 82 } 83 84 if(display instanceof ccs.DisplayData){ 85 cc.displayFactory.addDisplay(this._bone, decoDisplay, display); 86 //! if changed display index is current display index, then change current display to the new display 87 if(index == this._displayIndex) { 88 this._displayIndex = -1; 89 this.changeDisplayWithIndex(index, false); 90 } 91 return; 92 } 93 94 var displayData = null; 95 if (display instanceof ccs.Skin) { 96 display.setBone(this._bone); 97 displayData = new ccs.SpriteDisplayData(); 98 ccs.displayFactory.initSpriteDisplay(this._bone, decoDisplay, display.getDisplayName(), display); 99 100 var spriteDisplayData = decoDisplay.getDisplayData(); 101 if (spriteDisplayData instanceof ccs.SpriteDisplayData) { 102 display.setSkinData(spriteDisplayData.skinData); 103 displayData.skinData = spriteDisplayData.skinData; 104 } else { 105 var find = false; 106 for (var i = locDisplayList.length - 2; i >= 0; i--) { 107 var dd = locDisplayList[i]; 108 var sdd = dd.getDisplayData(); 109 if (sdd instanceof ccs.SpriteDisplayData) { 110 find = true; 111 display.setSkinData(sdd.skinData); 112 displayData.skinData = sdd.skinData; 113 break; 114 } 115 } 116 if (!find) 117 display.setSkinData(new ccs.BaseData()); 118 } 119 } else if (display instanceof cc.ParticleSystem){ 120 displayData = new ccs.ParticleDisplayData(); 121 display.removeFromParent(); 122 display.cleanup(); 123 var armature = this._bone.getArmature(); 124 if (armature) 125 display.setParent(armature); 126 } else if(display instanceof ccs.Armature) { 127 displayData = new ccs.ArmatureDisplayData(); 128 displayData.displayName = display.getName(); 129 display.setParentBone(this._bone); 130 } else 131 displayData = new ccs.DisplayData(); 132 decoDisplay.setDisplay(display); 133 decoDisplay.setDisplayData(displayData); 134 135 //! if changed display index is current display index, then change current display to the new display 136 if(index == this._displayIndex) { 137 this._displayIndex = -1; 138 this.changeDisplayWithIndex(index, false); 139 } 140 }, 141 142 _addDisplayOther:function(decoDisplay,display){ 143 var displayData = null; 144 if (display instanceof ccs.Skin){ 145 var skin = display; 146 skin.setBone(this._bone); 147 displayData = new ccs.SpriteDisplayData(); 148 displayData.displayName = skin.getDisplayName(); 149 ccs.displayFactory.initSpriteDisplay(this._bone, decoDisplay, skin.getDisplayName(), skin); 150 var spriteDisplayData = decoDisplay.getDisplayData(); 151 if (spriteDisplayData instanceof ccs.SpriteDisplayData) 152 skin.setSkinData(spriteDisplayData.skinData); 153 else{ 154 var find = false; 155 for (var i = this._decoDisplayList.length - 2; i >= 0; i--) { 156 var dd = this._decoDisplayList[i]; 157 var sdd = dd.getDisplayData(); 158 if (sdd) { 159 find = true; 160 skin.setSkinData(sdd.skinData); 161 displayData.skinData = sdd.skinData; 162 break; 163 } 164 } 165 if (!find) { 166 skin.setSkinData(new ccs.BaseData()); 167 } 168 skin.setSkinData(new ccs.BaseData()); 169 } 170 171 } 172 else if (display instanceof cc.ParticleSystem){ 173 displayData = new ccs.ParticleDisplayData(); 174 displayData.displayName = display._plistFile; 175 } 176 else if (display instanceof ccs.Armature){ 177 displayData = new ccs.ArmatureDisplayData(); 178 displayData.displayName = display.getName(); 179 display.setParentBone(this._bone); 180 } 181 else { 182 displayData = new ccs.DisplayData(); 183 } 184 decoDisplay.setDisplay(display); 185 decoDisplay.setDisplayData(displayData); 186 }, 187 188 /** 189 * Removes display node from list. 190 * @param {Number} index 191 */ 192 removeDisplay:function (index) { 193 this._decoDisplayList.splice(index, 1); 194 if (index === this._displayIndex) { 195 this.setCurrentDecorativeDisplay(null); 196 this._displayIndex = -1; 197 } 198 }, 199 200 /** 201 * Returns the display node list. 202 * @returns {Array} 203 */ 204 getDecorativeDisplayList:function(){ 205 return this._decoDisplayList; 206 }, 207 208 /** 209 * <p> 210 * Change display by index. You can just use this method to change display in the display list. <br/> 211 * The display list is just used for this bone, and it is the displays you may use in every frame. <br/> 212 * Note : if index is the same with prev index, the method will not effect <br/> 213 * </p> 214 * @param {Number} index The index of the display you want to change 215 * @param {Boolean} force If true, then force change display to specified display, or current display will set to display index edit in the flash every key frame. 216 */ 217 changeDisplayWithIndex:function (index, force) { 218 if (index >= this._decoDisplayList.length) { 219 cc.log("the index value is out of range"); 220 return; 221 } 222 this._forceChangeDisplay = force; 223 224 //if index is equal to current display index,then do nothing 225 if (this._displayIndex == index) 226 return; 227 228 this._displayIndex = index; 229 230 //! If displayIndex < 0, it means you want to hide you display 231 if (index < 0) { 232 if(this._displayRenderNode) { 233 this._displayRenderNode.removeFromParent(true); 234 this.setCurrentDecorativeDisplay(null); 235 } 236 return; 237 } 238 this.setCurrentDecorativeDisplay(this._decoDisplayList[index]); 239 }, 240 241 /** 242 * Change display by name. @see changeDisplayWithIndex. 243 * @param {String} name 244 * @param {Boolean} force 245 */ 246 changeDisplayWithName: function (name, force) { 247 var locDisplayList = this._decoDisplayList; 248 for (var i = 0; i < locDisplayList.length; i++) { 249 if (locDisplayList[i].getDisplayData().displayName == name) { 250 this.changeDisplayWithIndex(i, force); 251 break; 252 } 253 } 254 }, 255 256 /** 257 * Sets current decorative display. 258 * @param {ccs.DecorativeDisplay} decoDisplay 259 */ 260 setCurrentDecorativeDisplay:function (decoDisplay) { 261 var locCurrentDecoDisplay = this._currentDecoDisplay; 262 if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) { 263 if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector()) 264 locCurrentDecoDisplay.getColliderDetector().setActive(false); 265 } 266 267 this._currentDecoDisplay = decoDisplay; 268 locCurrentDecoDisplay = this._currentDecoDisplay; 269 if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) { 270 if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector()) 271 locCurrentDecoDisplay.getColliderDetector().setActive(true); 272 } 273 274 var displayRenderNode = (!locCurrentDecoDisplay) ? null : locCurrentDecoDisplay.getDisplay(); 275 276 var locRenderNode = this._displayRenderNode, locBone = this._bone; 277 if (locRenderNode) { 278 if (locRenderNode instanceof ccs.Armature) 279 locBone.setChildArmature(null); 280 locRenderNode.removeFromParent(true); 281 } 282 this._displayRenderNode = displayRenderNode; 283 284 if (displayRenderNode) { 285 if (displayRenderNode instanceof ccs.Armature) { 286 this._bone.setChildArmature(displayRenderNode); 287 displayRenderNode.setParentBone(this._bone); 288 } else if (displayRenderNode instanceof cc.ParticleSystem) { 289 if (displayRenderNode instanceof ccs.Armature) { 290 locBone.setChildArmature(displayRenderNode); 291 displayRenderNode.setParentBone(locBone); 292 } else if (displayRenderNode instanceof cc.ParticleSystem) 293 displayRenderNode.resetSystem(); 294 } 295 296 displayRenderNode.setColor(locBone.getDisplayedColor()); 297 displayRenderNode.setOpacity(locBone.getDisplayedOpacity()); 298 299 this._displayRenderNode.setVisible(this._visible); 300 this._displayType = this._currentDecoDisplay.getDisplayData().displayType; 301 }else 302 this._displayType = ccs.DISPLAY_TYPE_MAX; 303 }, 304 305 /** 306 * Returns the current display render node. 307 * @returns {cc.Node} 308 */ 309 getDisplayRenderNode:function () { 310 return this._displayRenderNode; 311 }, 312 313 /** 314 * Returns the type of display render node. 315 * @returns {Number} 316 */ 317 getDisplayRenderNodeType:function(){ 318 return this._displayType; 319 }, 320 321 /** 322 * Returns the index of display render node. 323 * @returns {Number} 324 */ 325 getCurrentDisplayIndex:function () { 326 return this._displayIndex; 327 }, 328 329 /** 330 * Returns the current decorative display 331 * @returns {ccs.DecorativeDisplay} 332 */ 333 getCurrentDecorativeDisplay:function () { 334 return this._currentDecoDisplay; 335 }, 336 337 /** 338 * Gets a decorative display by index. 339 * @param index 340 * @returns {ccs.DecorativeDisplay} 341 */ 342 getDecorativeDisplayByIndex:function (index) { 343 return this._decoDisplayList[index]; 344 }, 345 346 /** 347 * <p> 348 * Use BoneData to init the display list. 349 * If display is a sprite, and it have texture info in the TextureData, then use TextureData to init the display node's anchor point 350 * If the display is a Armature, then create a new Armature 351 * </p> 352 * @param {ccs.BoneData} boneData 353 */ 354 initDisplayList:function (boneData) { 355 this._decoDisplayList.length = 0; 356 if (!boneData) 357 return; 358 var displayList = boneData.displayDataList, decoList = this._decoDisplayList, locBone = this._bone; 359 for (var i = 0; i < displayList.length; i++) { 360 var displayData = displayList[i]; 361 var decoDisplay = ccs.DecorativeDisplay.create(); 362 decoDisplay.setDisplayData(displayData); 363 ccs.displayFactory.createDisplay(locBone, decoDisplay); 364 decoList.push(decoDisplay); 365 } 366 }, 367 368 /** 369 * Check if the position is inside the bone. 370 * @param {cc.Point|Number} point 371 * @param {Number} [y] 372 * @returns {boolean} 373 */ 374 containPoint: function (point, y) { 375 if (!this._visible || this._displayIndex < 0) 376 return false; 377 378 if (y !== undefined) 379 point = cc.p(point, y); 380 381 if(this._currentDecoDisplay.getDisplayData().displayType == ccs.DISPLAY_TYPE_SPRITE){ 382 /* 383 * First we first check if the point is in the sprite content rect. If false, then we continue to check 384 * the contour point. If this step is also false, then we can say the bone not contain this point. 385 * 386 */ 387 var sprite = this._currentDecoDisplay.getDisplay(); 388 sprite = sprite.getChildByTag(0); 389 return ccs.SPRITE_CONTAIN_POINT_WITH_RETURN(sprite, point); 390 } 391 return false; 392 }, 393 394 /** 395 * <p> 396 * Sets whether the display is visible <br/> 397 * The default value is true, a node is default to visible 398 * </p> 399 * @param {boolean} visible 400 */ 401 setVisible:function (visible) { 402 if (!this._displayRenderNode) 403 return; 404 this._visible = visible; 405 this._displayRenderNode.setVisible(visible); 406 }, 407 408 /** 409 * Determines if the display is visible 410 * @returns {boolean} true if the node is visible, false if the node is hidden. 411 */ 412 isVisible:function () { 413 return this._visible; 414 }, 415 416 getContentSize:function () { 417 if (!this._displayRenderNode) 418 return cc.size(0, 0); 419 return this._displayRenderNode.getContentSize(); 420 }, 421 422 getBoundingBox:function () { 423 if (!this._displayRenderNode) 424 return cc.rect(0, 0, 0, 0); 425 return this._displayRenderNode.getBoundingBox(); 426 }, 427 428 getAnchorPoint:function () { 429 if (!this._displayRenderNode) 430 return cc.p(0, 0); 431 return this._displayRenderNode.getAnchorPoint(); 432 }, 433 434 getAnchorPointInPoints:function () { 435 if (!this._displayRenderNode) 436 return cc.p(0, 0); 437 return this._displayRenderNode.getAnchorPointInPoints(); 438 }, 439 440 getForceChangeDisplay:function () { 441 return this._forceChangeDisplay; 442 }, 443 444 release:function () { 445 this._decoDisplayList = null; 446 if (this._displayRenderNode) { 447 this._displayRenderNode.removeFromParent(true); 448 this._displayRenderNode = null; 449 } 450 } 451 }); 452 453 /** 454 * Allocates and initializes a display manager with ccs.Bone. 455 * @param {ccs.Bone} bone 456 * @returns {ccs.DisplayManager} 457 */ 458 ccs.DisplayManager.create = function (bone) { 459 var displayManager = new ccs.DisplayManager(); 460 if (displayManager && displayManager.init(bone)) 461 return displayManager; 462 return null; 463 };