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