1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3 
  4  http://www.cocos2d-x.org
  5 
  6  Permission is hereby granted, free of charge, to any person obtaining a copy
  7  of this software and associated documentation files (the "Software"), to deal
  8  in the Software without restriction, including without limitation the rights
  9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10  copies of the Software, and to permit persons to whom the Software is
 11  furnished to do so, subject to the following conditions:
 12 
 13  The above copyright notice and this permission notice shall be included in
 14  all copies or substantial portions of the Software.
 15 
 16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22  THE SOFTWARE.
 23  ****************************************************************************/
 24 
 25 /**
 26  * The display manager of CocoStudio
 27  * @Class
 28  * @extend cc.Class
 29  */
 30 ccs.DisplayManager = ccs.Class.extend(/** @lends cc.DisplayManager */{
 31     _decoDisplayList:null,
 32     _currentDecoDisplay:null,
 33     _displayRenderNode:null,
 34     _displayIndex:-1,
 35     _forceChangeDisplay:false,
 36     _bone:null,
 37     _visible:true,
 38     _displayType: null,
 39     ctor:function () {
 40         this._decoDisplayList = [];
 41         this._currentDecoDisplay = null;
 42         this._displayRenderNode = null;
 43         this._displayIndex = -1;
 44         this._forceChangeDisplay = false;
 45         this._bone = null;
 46         this._visible = true;
 47         this._displayType = ccs.DISPLAY_TYPE_MAX;
 48     },
 49 
 50     init:function (bone) {
 51         this._bone = bone;
 52         this.initDisplayList(bone.getBoneData());
 53         return true;
 54     },
 55 
 56     addDisplay: function (displayData, index) {
 57         var decoDisplay = null;
 58         if (index >= 0 && index < this._decoDisplayList.length) {
 59             decoDisplay = this._decoDisplayList[index];
 60         }
 61         else {
 62             decoDisplay = ccs.DecorativeDisplay.create();
 63             this._decoDisplayList.push(decoDisplay);
 64         }
 65 
 66         if(displayData instanceof ccs.DisplayData){
 67             ccs.DisplayFactory.addDisplay(this._bone, decoDisplay, displayData);
 68         }else{
 69             this._addDisplayOther(decoDisplay,displayData);
 70         }
 71 
 72         //! if changed display index is current display index, then change current display to the new display
 73         if (index == this._displayIndex) {
 74             this._displayIndex = -1;
 75             this.changeDisplayWithIndex(index, false);
 76         }
 77     },
 78 
 79     _addDisplayOther:function(decoDisplay,display){
 80         var displayData = null;
 81         if (display instanceof ccs.Skin){
 82             var skin = display;
 83             skin.setBone(this._bone);
 84             displayData = new ccs.SpriteDisplayData();
 85             displayData.displayName = skin.getDisplayName();
 86             ccs.DisplayFactory.initSpriteDisplay(this._bone, decoDisplay, skin.getDisplayName(), skin);
 87             var spriteDisplayData = decoDisplay.getDisplayData();
 88             if (spriteDisplayData instanceof ccs.SpriteDisplayData)
 89                 skin.setSkinData(spriteDisplayData.skinData);
 90             else{
 91                 var find = false;
 92                 for (var i = this._decoDisplayList.length - 2; i >= 0; i--) {
 93                     var dd = this._decoDisplayList[i];
 94                     var sdd = dd.getDisplayData();
 95                     if (sdd) {
 96                         find = true;
 97                         skin.setSkinData(sdd.skinData);
 98                         displayData.skinData = sdd.skinData;
 99                         break;
100                     }
101                 }
102                 if (!find) {
103                     skin.setSkinData(new ccs.BaseData());
104                 }
105                 skin.setSkinData(new ccs.BaseData());
106             }
107                 
108         }
109         else if (display instanceof cc.ParticleSystem){
110             displayData = new ccs.ParticleDisplayData();
111             displayData.displayName = display._plistFile;
112         }
113         else if (display instanceof ccs.Armature){
114             displayData = new ccs.ArmatureDisplayData();
115             displayData.displayName = display.getName();
116             display.setParentBone(this._bone);
117         }
118         else  {
119             displayData = new ccs.DisplayData();
120         }
121         decoDisplay.setDisplay(display);
122         decoDisplay.setDisplayData(displayData);
123     },
124 
125     removeDisplay:function (index) {
126         this._decoDisplayList.splice(index, 1);
127         if (index == this._displayIndex) {
128             this.setCurrentDecorativeDisplay(null);
129         }
130     },
131 
132     getDecorativeDisplayList:function(){
133         return this._decoDisplayList;
134     },
135 
136     changeDisplayWithIndex:function (index, force) {
137         if (index >= this._decoDisplayList.length) {
138             cc.log("the index value is out of range");
139             return;
140         }
141 
142         this._forceChangeDisplay = force;
143 
144         //this._displayIndex == -1, it means you want to hide you display
145         if (index < 0) {
146             this._displayIndex = index;
147             if (this._displayRenderNode) {
148                 this._displayRenderNode.removeFromParent(true);
149                 this.setCurrentDecorativeDisplay(null);
150                 this._displayRenderNode = null;
151             }
152             return;
153         }
154 
155         //if index is equal to current display index,then do nothing
156         if (this._displayIndex == index) {
157             return;
158         }
159         this._displayIndex = index;
160 
161         var decoDisplay = this._decoDisplayList[this._displayIndex];
162         if(!decoDisplay){
163             return;
164         }
165         this.setCurrentDecorativeDisplay(decoDisplay);
166     },
167 
168     changeDisplayWithName: function (name, force) {
169         for (var i = 0; i < this._decoDisplayList.length; i++) {
170             if (this._decoDisplayList[i].getDisplayData().displayName == name) {
171                 this.changeDisplayWithIndex(i, force);
172                 break;
173             }
174         }
175     },
176 
177     setCurrentDecorativeDisplay:function (decoDisplay) {
178         var locCurrentDecoDisplay = this._currentDecoDisplay;
179         if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
180             if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector()) {
181                 locCurrentDecoDisplay.getColliderDetector().setActive(false);
182             }
183         }
184 
185         this._currentDecoDisplay = decoDisplay;
186         locCurrentDecoDisplay = this._currentDecoDisplay;
187         if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
188             if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector()) {
189                 locCurrentDecoDisplay.getColliderDetector().setActive(true);
190             }
191         }
192 
193         var displayRenderNode = locCurrentDecoDisplay == null ? null : locCurrentDecoDisplay.getDisplay();
194         if (this._displayRenderNode) {
195             if (this._displayRenderNode instanceof ccs.Armature) {
196                 this._bone.setChildArmature(null);
197             }
198             this._displayRenderNode.removeFromParent(true);
199             this._displayRenderNode = null;
200         }
201 
202         this._displayRenderNode = displayRenderNode;
203 
204         if (displayRenderNode) {
205             if (displayRenderNode instanceof ccs.Armature) {
206                 this._bone.setChildArmature(displayRenderNode);
207             }else if(displayRenderNode instanceof cc.ParticleSystem) {
208                 displayRenderNode.resetSystem();
209             }
210             if (displayRenderNode.RGBAProtocol)            {
211                 displayRenderNode.setColor(this._bone.getDisplayedColor());
212                 displayRenderNode.setOpacity(this._bone.getDisplayedOpacity());
213             }
214             displayRenderNode.retain();
215             this._displayType = this._currentDecoDisplay.getDisplayData().displayType;
216             //todo
217             //this._displayRenderNode.setVisible(this._visible);
218         }else{
219             this._displayType = ccs.DISPLAY_TYPE_MAX;
220         }
221     },
222 
223     getDisplayRenderNode:function () {
224         return this._displayRenderNode;
225     },
226 
227     getDisplayRenderNodeType:function(){
228         return this._displayType;
229     },
230 
231     getCurrentDisplayIndex:function () {
232         return this._displayIndex;
233     },
234 
235     getCurrentDecorativeDisplay:function () {
236         return this._currentDecoDisplay;
237     },
238 
239     getDecorativeDisplayByIndex:function (index) {
240         return this._decoDisplayList[index];
241     },
242 
243     initDisplayList:function (boneData) {
244         this._decoDisplayList = [];
245         if (!boneData) {
246             return;
247         }
248         var displayList = boneData.displayDataList;
249         for (var i = 0; i < displayList.length; i++) {
250             var displayData = displayList[i];
251             var decoDisplay = ccs.DecorativeDisplay.create();
252             decoDisplay.setDisplayData(displayData);
253 
254             ccs.DisplayFactory.createDisplay(this._bone, decoDisplay);
255 
256             this._decoDisplayList.push(decoDisplay);
257         }
258     },
259 
260     containPoint: function (point, y) {
261         var p = cc.p(0, 0);
262         if (y === undefined) {
263             p.x = point.x;
264             p.y = point.y;
265         } else {
266             p.x = point;
267             p.y = y;
268         }
269         if (!this._visible || this._displayIndex < 0) {
270             return false;
271         }
272 
273         var ret = false;
274         switch (this._currentDecoDisplay.getDisplayData().displayType) {
275             case ccs.DISPLAY_TYPE_SPRITE:
276                 /*
277                  *  First we first check if the point is in the sprite content rect. If false, then we continue to check
278                  *  the contour point. If this step is also false, then we can say the bone not contain this point.
279                  *
280                  */
281                 var outPoint = cc.p(0, 0);
282                 var sprite = this._currentDecoDisplay.getDisplay();
283                 sprite = sprite.getChildByTag(0);
284                 ret = ccs.SPRITE_CONTAIN_POINT_WITH_RETURN(sprite, p, outPoint);
285                 break;
286             default:
287                 break;
288         }
289         return ret;
290     },
291 
292     setVisible:function (visible) {
293         if (!this._displayRenderNode) {
294             return;
295         }
296         this._visible = visible;
297         this._displayRenderNode.setVisible(visible);
298     },
299 
300     isVisible:function () {
301         return this._visible;
302     },
303 
304     getContentSize:function () {
305         if (!this._displayRenderNode) {
306             return  cc.size(0, 0);
307         }
308         return this._displayRenderNode.getContentSize();
309     },
310 
311     getBoundingBox:function () {
312         if (!this._displayRenderNode) {
313             return cc.rect(0, 0, 0, 0);
314         }
315         return this._displayRenderNode.getBoundingBox();
316     },
317 
318     getAnchorPoint:function () {
319         if (!this._displayRenderNode) {
320             return  cc.p(0, 0);
321         }
322         return this._displayRenderNode.getAnchorPoint();
323     },
324 
325     getAnchorPointInPoints:function () {
326         if (!this._displayRenderNode) {
327             return  cc.p(0, 0);
328         }
329         return this._displayRenderNode.getAnchorPointInPoints();
330     },
331 
332     getForceChangeDisplay:function () {
333         return this._forceChangeDisplay;
334     },
335 
336     release:function () {
337         this._decoDisplayList = [];
338         if (this._displayRenderNode) {
339             this._displayRenderNode.removeFromParent(true);
340             this._displayRenderNode = null;
341         }
342     }
343 
344 });
345 
346 ccs.DisplayManager.create = function (bone) {
347     var displayManager = new ccs.DisplayManager();
348     if (displayManager && displayManager.init(bone)) {
349         return displayManager;
350     }
351     return null;
352 };