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 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:-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 (display, index) {
 58 
 59         var decoDisplay = null;
 60 
 61         if( (index >= 0) && (index < this._decoDisplayList.length) )
 62         {
 63             decoDisplay = this._decoDisplayList[index];
 64         }
 65         else
 66         {
 67             decoDisplay = ccs.DecorativeDisplay.create();
 68             this._decoDisplayList.push(decoDisplay);
 69         }
 70 
 71         var displayData = null;
 72         if (display instanceof ccs.Skin)
 73         {
 74             var skin = display;
 75             skin.setBone(this._bone);
 76             displayData = new ccs.SpriteDisplayData();
 77 
 78             ccs.DisplayFactory.initSpriteDisplay(this._bone, decoDisplay, skin.getDisplayName(), skin);
 79 
 80             var spriteDisplayData = decoDisplay.getDisplayData();
 81             if (spriteDisplayData instanceof ccs.SpriteDisplayData)
 82             {
 83                 skin.setSkinData(spriteDisplayData.skinData);
 84                 displayData.skinData = spriteDisplayData.skinData;
 85             }
 86         else
 87             {
 88                 var find = false;
 89 
 90                 for (var i = this._decoDisplayList.length - 2; i>=0; i--)
 91                 {
 92                     var dd = this._decoDisplayList[i];
 93                     var sdd = dd.getDisplayData();
 94                     if (sdd instanceof ccs.SpriteDisplayData)
 95                     {
 96                         find = true;
 97                         skin.setSkinData(sdd.skinData);
 98                         displayData.skinData = sdd.skinData;
 99                         break;
100                     }
101                 }
102 //
103 //                if (!find)
104 //                {
105 //                    BaseData baseData;
106 //                    skin.setSkinData(baseData);
107 //                }
108             }
109         }
110         else if (display instanceof cc.ParticleSystem)
111         {
112             displayData = new ccs.ParticleDisplayData();
113 
114             display.removeFromParent();
115             display.cleanup();
116 
117             var armature = this._bone.getArmature();
118             if (armature)
119             {
120                 display.setParent(armature);
121             }
122         }
123         else if(display instanceof ccs.Armature)
124         {
125             var armature = display;
126             displayData = new ccs.ArmatureDisplayData();
127             displayData.displayName = armature.getName();
128             armature.setParentBone(this._bone);
129         }
130         else
131         {
132             displayData = new ccs.DisplayData();
133         }
134 
135         decoDisplay.setDisplay(display);
136         decoDisplay.setDisplayData(displayData);
137 
138         //! if changed display index is current display index, then change current display to the new display
139         if(index == this._displayIndex)
140         {
141             this._displayIndex = -1;
142             this.changeDisplayWithIndex(index, false);
143         }
144 //        var decoDisplay = null;
145 //        if (index >= 0 && index < this._decoDisplayList.length) {
146 //            decoDisplay = this._decoDisplayList[index];
147 //        }
148 //        else {
149 //            decoDisplay = ccs.DecorativeDisplay.create();
150 //            this._decoDisplayList.push(decoDisplay);
151 //        }
152 //
153 //        if(displayData instanceof ccs.DisplayData){
154 //            ccs.DisplayFactory.addDisplay(this._bone, decoDisplay, displayData);
155 //        }else{
156 //            this._addDisplayOther(decoDisplay,displayData);
157 //        }
158 //
159 //        //! if changed display index is current display index, then change current display to the new display
160 //        if (index == this._displayIndex) {
161 //            this._displayIndex = -1;
162 //            this.changeDisplayWithIndex(index, false);
163 //        }
164     },
165 
166     _addDisplayOther:function(decoDisplay,display){
167         var displayData = null;
168         if (display instanceof ccs.Skin){
169             var skin = display;
170             skin.setBone(this._bone);
171             displayData = new ccs.SpriteDisplayData();
172             displayData.displayName = skin.getDisplayName();
173             ccs.DisplayFactory.initSpriteDisplay(this._bone, decoDisplay, skin.getDisplayName(), skin);
174             var spriteDisplayData = decoDisplay.getDisplayData();
175             if (spriteDisplayData instanceof ccs.SpriteDisplayData)
176                 skin.setSkinData(spriteDisplayData.skinData);
177             else{
178                 var find = false;
179                 for (var i = this._decoDisplayList.length - 2; i >= 0; i--) {
180                     var dd = this._decoDisplayList[i];
181                     var sdd = dd.getDisplayData();
182                     if (sdd) {
183                         find = true;
184                         skin.setSkinData(sdd.skinData);
185                         displayData.skinData = sdd.skinData;
186                         break;
187                     }
188                 }
189                 if (!find) {
190                     skin.setSkinData(new ccs.BaseData());
191                 }
192                 skin.setSkinData(new ccs.BaseData());
193             }
194                 
195         }
196         else if (display instanceof cc.ParticleSystem){
197             displayData = new ccs.ParticleDisplayData();
198             displayData.displayName = display._plistFile;
199         }
200         else if (display instanceof ccs.Armature){
201             displayData = new ccs.ArmatureDisplayData();
202             displayData.displayName = display.getName();
203             display.setParentBone(this._bone);
204         }
205         else  {
206             displayData = new ccs.DisplayData();
207         }
208         decoDisplay.setDisplay(display);
209         decoDisplay.setDisplayData(displayData);
210     },
211 
212     removeDisplay:function (index) {
213         this._decoDisplayList.splice(index, 1);
214         if (index == this._displayIndex) {
215             this.setCurrentDecorativeDisplay(null);
216         }
217     },
218 
219     getDecorativeDisplayList:function(){
220         return this._decoDisplayList;
221     },
222 
223     changeDisplayWithIndex:function (index, force) {
224         if (index >= this._decoDisplayList.length) {
225             cc.log("the index value is out of range");
226             return;
227         }
228 
229         this._forceChangeDisplay = force;
230 
231         //this._displayIndex == -1, it means you want to hide you display
232         if (index < 0) {
233             this._displayIndex = index;
234             if (this._displayRenderNode) {
235                 this._displayRenderNode.removeFromParent(true);
236                 this.setCurrentDecorativeDisplay(null);
237                 this._displayRenderNode = null;
238             }
239             return;
240         }
241 
242         //if index is equal to current display index,then do nothing
243         if (this._displayIndex == index) {
244             return;
245         }
246         this._displayIndex = index;
247 
248         var decoDisplay = this._decoDisplayList[this._displayIndex];
249         if(!decoDisplay){
250             return;
251         }
252         this.setCurrentDecorativeDisplay(decoDisplay);
253     },
254 
255     changeDisplayWithName: function (name, force) {
256         for (var i = 0; i < this._decoDisplayList.length; i++) {
257             if (this._decoDisplayList[i].getDisplayData().displayName == name) {
258                 this.changeDisplayWithIndex(i, force);
259                 break;
260             }
261         }
262     },
263 
264     setCurrentDecorativeDisplay:function (decoDisplay) {
265         var locCurrentDecoDisplay = this._currentDecoDisplay;
266         if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
267             if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector()) {
268                 locCurrentDecoDisplay.getColliderDetector().setActive(false);
269             }
270         }
271 
272         this._currentDecoDisplay = decoDisplay;
273         locCurrentDecoDisplay = this._currentDecoDisplay;
274         if (ccs.ENABLE_PHYSICS_CHIPMUNK_DETECT || ccs.ENABLE_PHYSICS_SAVE_CALCULATED_VERTEX) {
275             if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector()) {
276                 locCurrentDecoDisplay.getColliderDetector().setActive(true);
277             }
278         }
279 
280         var displayRenderNode = locCurrentDecoDisplay == null ? null : locCurrentDecoDisplay.getDisplay();
281         if (this._displayRenderNode) {
282             if (this._displayRenderNode instanceof ccs.Armature) {
283                 this._bone.setChildArmature(null);
284             }
285             this._displayRenderNode.removeFromParent(true);
286             this._displayRenderNode = null;
287         }
288 
289         this._displayRenderNode = displayRenderNode;
290 
291         if (displayRenderNode) {
292             if (displayRenderNode instanceof ccs.Armature) {
293                 this._bone.setChildArmature(displayRenderNode);
294             }else if(displayRenderNode instanceof cc.ParticleSystem) {
295                 displayRenderNode.resetSystem();
296             }
297             if (displayRenderNode.RGBAProtocol)            {
298                 displayRenderNode.setColor(this._bone.getDisplayedColor());
299                 displayRenderNode.setOpacity(this._bone.getDisplayedOpacity());
300             }
301             displayRenderNode.retain();
302             this._displayType = this._currentDecoDisplay.getDisplayData().displayType;
303             //todo
304             //this._displayRenderNode.setVisible(this._visible);
305         }else{
306             this._displayType = ccs.DISPLAY_TYPE_MAX;
307         }
308     },
309 
310     getDisplayRenderNode:function () {
311         return this._displayRenderNode;
312     },
313 
314     getDisplayRenderNodeType:function(){
315         return this._displayType;
316     },
317 
318     getCurrentDisplayIndex:function () {
319         return this._displayIndex;
320     },
321 
322     getCurrentDecorativeDisplay:function () {
323         return this._currentDecoDisplay;
324     },
325 
326     getDecorativeDisplayByIndex:function (index) {
327         return this._decoDisplayList[index];
328     },
329 
330     initDisplayList:function (boneData) {
331         this._decoDisplayList = [];
332         if (!boneData) {
333             return;
334         }
335         var displayList = boneData.displayDataList;
336         for (var i = 0; i < displayList.length; i++) {
337             var displayData = displayList[i];
338             var decoDisplay = ccs.DecorativeDisplay.create();
339             decoDisplay.setDisplayData(displayData);
340 
341             ccs.DisplayFactory.createDisplay(this._bone, decoDisplay);
342 
343             this._decoDisplayList.push(decoDisplay);
344         }
345     },
346 
347     containPoint: function (point, y) {
348         var p = cc.p(0, 0);
349         if (y === undefined) {
350             p.x = point.x;
351             p.y = point.y;
352         } else {
353             p.x = point;
354             p.y = y;
355         }
356         if (!this._visible || this._displayIndex < 0) {
357             return false;
358         }
359 
360         var ret = false;
361         switch (this._currentDecoDisplay.getDisplayData().displayType) {
362             case ccs.DISPLAY_TYPE_SPRITE:
363                 /*
364                  *  First we first check if the point is in the sprite content rect. If false, then we continue to check
365                  *  the contour point. If this step is also false, then we can say the bone not contain this point.
366                  *
367                  */
368                 var outPoint = cc.p(0, 0);
369                 var sprite = this._currentDecoDisplay.getDisplay();
370                 sprite = sprite.getChildByTag(0);
371                 ret = ccs.SPRITE_CONTAIN_POINT_WITH_RETURN(sprite, p, outPoint);
372                 break;
373             default:
374                 break;
375         }
376         return ret;
377     },
378 
379     setVisible:function (visible) {
380         if (!this._displayRenderNode) {
381             return;
382         }
383         this._visible = visible;
384         this._displayRenderNode.setVisible(visible);
385     },
386 
387     isVisible:function () {
388         return this._visible;
389     },
390 
391     getContentSize:function () {
392         if (!this._displayRenderNode) {
393             return  cc.size(0, 0);
394         }
395         return this._displayRenderNode.getContentSize();
396     },
397 
398     getBoundingBox:function () {
399         if (!this._displayRenderNode) {
400             return cc.rect(0, 0, 0, 0);
401         }
402         return this._displayRenderNode.getBoundingBox();
403     },
404 
405     getAnchorPoint:function () {
406         if (!this._displayRenderNode) {
407             return  cc.p(0, 0);
408         }
409         return this._displayRenderNode.getAnchorPoint();
410     },
411 
412     getAnchorPointInPoints:function () {
413         if (!this._displayRenderNode) {
414             return  cc.p(0, 0);
415         }
416         return this._displayRenderNode.getAnchorPointInPoints();
417     },
418 
419     getForceChangeDisplay:function () {
420         return this._forceChangeDisplay;
421     },
422 
423     release:function () {
424         this._decoDisplayList = [];
425         if (this._displayRenderNode) {
426             this._displayRenderNode.removeFromParent(true);
427             this._displayRenderNode = null;
428         }
429     }
430 
431 });
432 
433 ccs.DisplayManager.create = function (bone) {
434     var displayManager = new ccs.DisplayManager();
435     if (displayManager && displayManager.init(bone)) {
436         return displayManager;
437     }
438     return null;
439 };