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 ccs.DisplayManager = ccs.Class.extend({
 26     _decoDisplayList:null,
 27     _currentDecoDisplay:null,
 28     _displayRenderNode:null,
 29     _displayIndex:-1,
 30     _forceChangeDisplay:false,
 31     _bone:null,
 32     _visible:true,
 33     _displayType: null,
 34     ctor:function () {
 35         this._decoDisplayList = [];
 36         this._currentDecoDisplay = null;
 37         this._displayRenderNode = null;
 38         this._displayIndex = -1;
 39         this._forceChangeDisplay = false;
 40         this._bone = null;
 41         this._visible = true;
 42         this._displayType = ccs.DisplayType.max;
 43     },
 44 
 45     init:function (bone) {
 46         this._bone = bone;
 47         this.initDisplayList(bone.getBoneData());
 48         return true;
 49     },
 50 
 51     addDisplay: function (displayData, index) {
 52         var decoDisplay = null;
 53         if (index >= 0 && index < this._decoDisplayList.length) {
 54             decoDisplay = this._decoDisplayList[index];
 55         }
 56         else {
 57             decoDisplay = ccs.DecotativeDisplay.create();
 58             this._decoDisplayList.push(decoDisplay);
 59         }
 60 
 61         if(displayData instanceof ccs.DisplayData){
 62             ccs.DisplayFactory.addDisplay(this._bone, decoDisplay, displayData);
 63         }else{
 64             this._addDisplayOther(decoDisplay,displayData);
 65         }
 66 
 67         //! if changed display index is current display index, then change current display to the new display
 68         if (index == this._displayIndex) {
 69             this._displayIndex = -1;
 70             this.changeDisplayWithIndex(index, false);
 71         }
 72     },
 73 
 74     _addDisplayOther:function(decoDisplay,display){
 75         var displayData = null;
 76         if (display instanceof ccs.Skin){
 77             var skin = display;
 78             skin.setBone(this._bone);
 79             displayData = new ccs.SpriteDisplayData();
 80             displayData.displayName = skin.getDisplayName();
 81             ccs.DisplayFactory.initSpriteDisplay(this._bone, decoDisplay, skin.getDisplayName(), skin);
 82             var spriteDisplayData = decoDisplay.getDisplayData();
 83             if (spriteDisplayData instanceof ccs.SpriteDisplayData)
 84                 skin.setSkinData(spriteDisplayData.skinData);
 85             else{
 86                 var find = false;
 87                 for (var i = this._decoDisplayList.length - 2; i >= 0; i--) {
 88                     var dd = this._decoDisplayList[i];
 89                     var sdd = dd.getDisplayData();
 90                     if (sdd) {
 91                         find = true;
 92                         skin.setSkinData(sdd.skinData);
 93                         displayData.skinData = sdd.skinData;
 94                         break;
 95                     }
 96                 }
 97                 if (!find) {
 98                     skin.setSkinData(new ccs.BaseData());
 99                 }
100                 skin.setSkinData(new ccs.BaseData());
101             }
102                 
103         }
104         else if (display instanceof cc.ParticleSystem){
105             displayData = new ccs.ParticleDisplayData();
106             displayData.displayName = display._plistFile;
107         }
108         else if (display instanceof ccs.Armature){
109             displayData = new ccs.ArmatureDisplayData();
110             displayData.displayName = display.getName();
111             display.setParentBone(this._bone);
112         }
113         else  {
114             displayData = new ccs.DisplayData();
115         }
116         decoDisplay.setDisplay(display);
117         decoDisplay.setDisplayData(displayData);
118     },
119 
120     removeDisplay:function (index) {
121         cc.ArrayRemoveObjectAtIndex(this._decoDisplayList, index);
122         if (index == this._displayIndex) {
123             this.setCurrentDecorativeDisplay(null);
124         }
125     },
126 
127     getDecorativeDisplayList:function(){
128         return this._decoDisplayList;
129     },
130 
131     changeDisplayWithIndex:function (index, force) {
132         if (index >= this._decoDisplayList.length) {
133             cc.log("the index value is out of range");
134             return;
135         }
136 
137         this._forceChangeDisplay = force;
138 
139         //this._displayIndex == -1, it means you want to hide you display
140         if (index < 0) {
141             this._displayIndex = index;
142             if (this._displayRenderNode) {
143                 this._displayRenderNode.removeFromParent(true);
144                 this.setCurrentDecorativeDisplay(null);
145                 this._displayRenderNode = null;
146             }
147             return;
148         }
149 
150         //if index is equal to current display index,then do nothing
151         if (this._displayIndex == index) {
152             return;
153         }
154         this._displayIndex = index;
155 
156         var decoDisplay = this._decoDisplayList[this._displayIndex];
157         if(!decoDisplay){
158             return;
159         }
160         this.setCurrentDecorativeDisplay(decoDisplay);
161     },
162 
163     changeDisplayWithName: function (name, force) {
164         for (var i = 0; i < this._decoDisplayList.length; i++) {
165             if (this._decoDisplayList[i].getDisplayData().displayName == name) {
166                 this.changeDisplayWithIndex(i, force);
167                 break;
168             }
169         }
170     },
171 
172     setCurrentDecorativeDisplay:function (decoDisplay) {
173         var locCurrentDecoDisplay = this._currentDecoDisplay;
174         if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
175             if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector()) {
176                 locCurrentDecoDisplay.getColliderDetector().setActive(false);
177             }
178         }
179 
180         this._currentDecoDisplay = decoDisplay;
181         locCurrentDecoDisplay = this._currentDecoDisplay;
182         if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
183             if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector()) {
184                 locCurrentDecoDisplay.getColliderDetector().setActive(true);
185             }
186         }
187 
188         var displayRenderNode = locCurrentDecoDisplay == null ? null : locCurrentDecoDisplay.getDisplay();
189         if (this._displayRenderNode) {
190             if (this._displayRenderNode instanceof ccs.Armature) {
191                 this._bone.setChildArmature(null);
192             }
193             this._displayRenderNode.removeFromParent(true);
194             this._displayRenderNode = null;
195         }
196 
197         this._displayRenderNode = displayRenderNode;
198 
199         if (displayRenderNode) {
200             if (displayRenderNode instanceof ccs.Armature) {
201                 this._bone.setChildArmature(displayRenderNode);
202             }else if(displayRenderNode instanceof cc.ParticleSystem) {
203                 displayRenderNode.resetSystem();
204             }
205             if (displayRenderNode.RGBAProtocol)            {
206                 displayRenderNode.setColor(this._bone.getDisplayedColor());
207                 displayRenderNode.setOpacity(this._bone.getDisplayedOpacity());
208             }
209             displayRenderNode.retain();
210             this._displayType = this._currentDecoDisplay.getDisplayData().displayType;
211             //todo
212             //this._displayRenderNode.setVisible(this._visible);
213         }else{
214             this._displayType = ccs.DisplayType.max;
215         }
216     },
217 
218     getDisplayRenderNode:function () {
219         return this._displayRenderNode;
220     },
221 
222     getDisplayRenderNodeType:function(){
223         return this._displayType;
224     },
225 
226     getCurrentDisplayIndex:function () {
227         return this._displayIndex;
228     },
229 
230     getCurrentDecorativeDisplay:function () {
231         return this._currentDecoDisplay;
232     },
233 
234     getDecorativeDisplayByIndex:function (index) {
235         return this._decoDisplayList[index];
236     },
237 
238     initDisplayList:function (boneData) {
239         this._decoDisplayList = [];
240         if (!boneData) {
241             return;
242         }
243         var displayList = boneData.displayDataList;
244         for (var i = 0; i < displayList.length; i++) {
245             var displayData = displayList[i];
246             var decoDisplay = ccs.DecotativeDisplay.create();
247             decoDisplay.setDisplayData(displayData);
248 
249             ccs.DisplayFactory.createDisplay(this._bone, decoDisplay);
250 
251             this._decoDisplayList.push(decoDisplay);
252         }
253     },
254 
255     containPoint: function (point, y) {
256         var p = cc.p(0, 0);
257         if (y === undefined) {
258             p.x = point.x;
259             p.y = point.y;
260         } else {
261             p.x = point;
262             p.y = y;
263         }
264         if (!this._visible || this._displayIndex < 0) {
265             return false;
266         }
267 
268         var ret = false;
269         switch (this._currentDecoDisplay.getDisplayData().displayType) {
270             case ccs.DisplayType.sprite:
271                 /*
272                  *  First we first check if the point is in the sprite content rect. If false, then we continue to check
273                  *  the contour point. If this step is also false, then we can say the bone not contain this point.
274                  *
275                  */
276                 var outPoint = cc.p(0, 0);
277                 var sprite = this._currentDecoDisplay.getDisplay();
278                 sprite = sprite.getChildByTag(0);
279                 ret = ccs.SPRITE_CONTAIN_POINT_WITH_RETURN(sprite, p, outPoint);
280                 break;
281             default:
282                 break;
283         }
284         return ret;
285     },
286 
287     setVisible:function (visible) {
288         if (!this._displayRenderNode) {
289             return;
290         }
291         this._visible = visible;
292         this._displayRenderNode.setVisible(visible);
293     },
294 
295     isVisible:function () {
296         return this._visible;
297     },
298 
299     getContentSize:function () {
300         if (!this._displayRenderNode) {
301             return  cc.size(0, 0);
302         }
303         return this._displayRenderNode.getContentSize();
304     },
305 
306     getBoundingBox:function () {
307         if (!this._displayRenderNode) {
308             return cc.rect(0, 0, 0, 0);
309         }
310         return this._displayRenderNode.getBoundingBox();
311     },
312 
313     getAnchorPoint:function () {
314         if (!this._displayRenderNode) {
315             return  cc.p(0, 0);
316         }
317         return this._displayRenderNode.getAnchorPoint();
318     },
319 
320     getAnchorPointInPoints:function () {
321         if (!this._displayRenderNode) {
322             return  cc.p(0, 0);
323         }
324         return this._displayRenderNode.getAnchorPointInPoints();
325     },
326 
327     getForceChangeDisplay:function () {
328         return this._forceChangeDisplay;
329     },
330 
331     release:function () {
332         this._decoDisplayList = [];
333         if (this._displayRenderNode) {
334             this._displayRenderNode.removeFromParent(true);
335             this._displayRenderNode = null;
336         }
337     }
338 
339 });
340 
341 ccs.DisplayManager.create = function (bone) {
342     var displayManager = new ccs.DisplayManager();
343     if (displayManager && displayManager.init(bone)) {
344         return displayManager;
345     }
346     return null;
347 };