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