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 Bone of Armature, it has bone data, display manager and transform data for armature.
 28  * @class
 29  * @extends ccs.Node
 30  *
 31  * @param {String} [name] The name of the bone
 32  * @example
 33  *
 34  * var bone = new ccs.Bone("head");
 35  *
 36  * @property {ccs.BoneData}         boneData                - The bone data
 37  * @property {ccs.Armature}         armature                - The armature
 38  * @property {ccs.Bone}             parentBone              - The parent bone
 39  * @property {ccs.Armature}         childArmature           - The child armature
 40  * @property {Array}                childrenBone            - <@readonly> All children bones
 41  * @property {ccs.Tween}            tween                   - <@readonly> Tween
 42  * @property {ccs.FrameData}        tweenData               - <@readonly> The tween data
 43  * @property {ccs.ColliderFilter}   colliderFilter          - The collider filter
 44  * @property {ccs.DisplayManager}   displayManager          - The displayManager
 45  * @property {Boolean}              ignoreMovementBoneData  - Indicate whether force the bone to show When CCArmature play a animation and there isn't a CCMovementBoneData of this bone in this CCMovementData.
 46  * @property {String}               name                    - The name of the bone
 47  * @property {Boolean}              blendDirty              - Indicate whether the blend is dirty
 48  *
 49  */
 50 ccs.Bone = ccs.Node.extend(/** @lends ccs.Bone# */{
 51     _boneData: null,
 52     _armature: null,
 53     _childArmature: null,
 54     _displayManager: null,
 55     ignoreMovementBoneData: false,
 56     _tween: null,
 57     _tweenData: null,
 58     _parentBone: null,
 59     _boneTransformDirty: false,
 60     _worldTransform: null,
 61     _blendFunc: null,
 62     blendDirty: false,
 63     _worldInfo: null,
 64     _armatureParentBone: null,
 65     _dataVersion: 0,
 66     _className: "Bone",
 67 
 68     ctor: function (name) {
 69         cc.Node.prototype.ctor.call(this);
 70         this._tweenData = null;
 71         this._parentBone = null;
 72         this._armature = null;
 73         this._childArmature = null;
 74         this._boneData = null;
 75         this._tween = null;
 76         this._displayManager = null;
 77         this.ignoreMovementBoneData = false;
 78 
 79         this._worldTransform = cc.affineTransformMake(1, 0, 0, 1, 0, 0);
 80         this._boneTransformDirty = true;
 81         this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
 82         this.blendDirty = false;
 83         this._worldInfo = null;
 84 
 85         this._armatureParentBone = null;
 86         this._dataVersion = 0;
 87 
 88         ccs.Bone.prototype.init.call(this, name);
 89     },
 90 
 91     /**
 92      * Initializes a ccs.Bone with the specified name
 93      * @param {String} name bone name
 94      * @return {Boolean}
 95      */
 96     init: function (name) {
 97 //        cc.Node.prototype.init.call(this);
 98         if (name)
 99             this._name = name;
100         this._tweenData = new ccs.FrameData();
101 
102         this._tween = new ccs.Tween(this);
103 
104         this._displayManager = new ccs.DisplayManager(this);
105 
106         this._worldInfo = new ccs.BaseData();
107         this._boneData = new ccs.BaseData();
108 
109         return true;
110     },
111 
112     /**
113      * Sets the boneData to ccs.Bone.
114      * @param {ccs.BoneData} boneData
115      */
116     setBoneData: function (boneData) {
117         cc.assert(boneData, "_boneData must not be null");
118 
119         if(this._boneData !== boneData)
120             this._boneData = boneData;
121 
122         this.setName(this._boneData.name);
123         this._localZOrder = this._boneData.zOrder;
124         this._displayManager.initDisplayList(boneData);
125     },
126 
127     /**
128      * Returns boneData of ccs.Bone.
129      * @return {ccs.BoneData}
130      */
131     getBoneData: function () {
132         return this._boneData;
133     },
134 
135     /**
136      * Sets the armature reference to ccs.Bone.
137      * @param {ccs.Armature} armature
138      */
139     setArmature: function (armature) {
140         this._armature = armature;
141         if (armature) {
142             this._tween.setAnimation(this._armature.getAnimation());
143             this._dataVersion = this._armature.getArmatureData().dataVersion;
144             this._armatureParentBone = this._armature.getParentBone();
145         } else
146             this._armatureParentBone = null;
147     },
148 
149     /**
150      * Returns the armature reference of ccs.Bone.
151      * @return {ccs.Armature}
152      */
153     getArmature: function () {
154         return this._armature;
155     },
156 
157     /**
158      * Updates worldTransform by tween data and updates display state
159      * @param {Number} delta
160      */
161     update: function (delta) {
162         if (this._parentBone)
163             this._boneTransformDirty = this._boneTransformDirty || this._parentBone.isTransformDirty();
164 
165         if (this._armatureParentBone && !this._boneTransformDirty)
166             this._boneTransformDirty = this._armatureParentBone.isTransformDirty();
167 
168         if (this._boneTransformDirty){
169             var locTweenData = this._tweenData;
170             if (this._dataVersion >= ccs.CONST_VERSION_COMBINED){
171                 ccs.TransformHelp.nodeConcat(locTweenData, this._boneData);
172                 locTweenData.scaleX -= 1;
173                 locTweenData.scaleY -= 1;
174             }
175 
176             var locWorldInfo = this._worldInfo;
177             locWorldInfo.copy(locTweenData);
178             locWorldInfo.x = locTweenData.x + this._position.x;
179             locWorldInfo.y = locTweenData.y + this._position.y;
180             locWorldInfo.scaleX = locTweenData.scaleX * this._scaleX;
181             locWorldInfo.scaleY = locTweenData.scaleY * this._scaleY;
182             locWorldInfo.skewX = locTweenData.skewX + this._skewX + cc.degreesToRadians(this._rotationX);
183             locWorldInfo.skewY = locTweenData.skewY + this._skewY - cc.degreesToRadians(this._rotationY);
184 
185             if(this._parentBone)
186                 this._applyParentTransform(this._parentBone);
187             else {
188                 if (this._armatureParentBone)
189                     this._applyParentTransform(this._armatureParentBone);
190             }
191 
192             ccs.TransformHelp.nodeToMatrix(locWorldInfo, this._worldTransform);
193             if (this._armatureParentBone)
194                 cc.affineTransformConcatIn(this._worldTransform, this._armature.getNodeToParentTransform());            //TODO TransformConcat
195         }
196 
197         ccs.displayFactory.updateDisplay(this, delta, this._boneTransformDirty || this._armature.getArmatureTransformDirty());
198         for(var i=0; i<this._children.length; i++) {
199             var childBone = this._children[i];
200             childBone.update(delta);
201         }
202         this._boneTransformDirty = false;
203     },
204 
205     _applyParentTransform: function (parent) {
206         var locWorldInfo = this._worldInfo;
207         var locParentWorldTransform = parent._worldTransform;
208         var locParentWorldInfo = parent._worldInfo;
209         var x = locWorldInfo.x;
210         var y = locWorldInfo.y;
211         locWorldInfo.x = x * locParentWorldTransform.a + y * locParentWorldTransform.c + locParentWorldInfo.x;
212         locWorldInfo.y = x * locParentWorldTransform.b + y * locParentWorldTransform.d + locParentWorldInfo.y;
213         locWorldInfo.scaleX = locWorldInfo.scaleX * locParentWorldInfo.scaleX;
214         locWorldInfo.scaleY = locWorldInfo.scaleY * locParentWorldInfo.scaleY;
215         locWorldInfo.skewX = locWorldInfo.skewX + locParentWorldInfo.skewX;
216         locWorldInfo.skewY = locWorldInfo.skewY + locParentWorldInfo.skewY;
217     },
218 
219     /**
220      * Sets BlendFunc to ccs.Bone.
221      * @param {cc.BlendFunc|Number} blendFunc blendFunc or src of blendFunc
222      * @param {Number} [dst] dst of blendFunc
223      */
224     setBlendFunc: function (blendFunc, dst) {
225         var locBlendFunc = this._blendFunc, srcValue, dstValue;
226         if(dst === undefined){
227             srcValue = blendFunc.src;
228             dstValue = blendFunc.dst;
229         } else {
230             srcValue = blendFunc;
231             dstValue = dst;
232         }
233         if (locBlendFunc.src !== srcValue || locBlendFunc.dst !== dstValue) {
234             locBlendFunc.src = srcValue;
235             locBlendFunc.dst = dstValue;
236             this.blendDirty = true;
237         }
238     },
239 
240     /**
241      * Updates display color
242      */
243     updateColor: function () {
244         var display = this._displayManager.getDisplayRenderNode();
245         if (display !== null) {
246             var cmd = this._renderCmd;
247             display.setColor(
248                 cc.color(
249                         cmd._displayedColor.r * this._tweenData.r / 255,
250                         cmd._displayedColor.g * this._tweenData.g / 255,
251                         cmd._displayedColor.b * this._tweenData.b / 255));
252             display.setOpacity(cmd._displayedOpacity * this._tweenData.a / 255);
253         }
254     },
255 
256     /**
257      * Updates display zOrder
258      */
259     updateZOrder: function () {
260         if (this._armature.getArmatureData().dataVersion >= ccs.CONST_VERSION_COMBINED) {
261             this.setLocalZOrder(this._tweenData.zOrder + this._boneData.zOrder);
262         } else {
263             this.setLocalZOrder(this._tweenData.zOrder);
264         }
265     },
266 
267     /**
268      * Adds a child to this bone, and it will let this child call setParent(ccs.Bone) function to set self to it's parent
269      * @param {ccs.Bone} child
270      */
271     addChildBone: function (child) {
272         cc.assert(child, "Argument must be non-nil");
273         cc.assert(!child.parentBone, "child already added. It can't be added again");
274 
275         if (this._children.indexOf(child) < 0) {
276             this._children.push(child);
277             child.setParentBone(this);
278         }
279     },
280 
281     /**
282      * Removes a child bone
283      * @param {ccs.Bone} bone
284      * @param {Boolean} recursion
285      */
286     removeChildBone: function (bone, recursion) {
287         if (this._children.length > 0 && this._children.getIndex(bone) !== -1 ) {
288             if(recursion) {
289                 var ccbones = bone._children;
290                 for(var i=0; i<ccbones.length; i++){
291                     var ccBone = ccbones[i];
292                     bone.removeChildBone(ccBone, recursion);
293                 }
294             }
295 
296             bone.setParentBone(null);
297             bone.getDisplayManager().setCurrentDecorativeDisplay(null);
298             cc.arrayRemoveObject(this._children, bone);
299         }
300     },
301 
302     /**
303      * Removes itself from its parent ccs.Bone.
304      * @param {Boolean} recursion
305      */
306     removeFromParent: function (recursion) {
307         if (this._parentBone)
308             this._parentBone.removeChildBone(this, recursion);
309     },
310 
311     /**
312      * Sets parent bone to ccs.Bone.
313      * If _parent is NUll, then also remove this bone from armature.
314      * It will not set the ccs.Armature, if you want to add the bone to a ccs.Armature, you should use ccs.Armature.addBone(bone, parentName).
315      * @param {ccs.Bone}  parent  the parent bone.
316      */
317     setParentBone: function (parent) {
318         this._parentBone = parent;
319     },
320 
321     /**
322      * Returns the parent bone of ccs.Bone.
323      * @returns {ccs.Bone}
324      */
325     getParentBone: function(){
326         return this._parentBone;
327     },
328 
329     /**
330      * Sets ccs.Bone's child armature
331      * @param {ccs.Armature} armature
332      */
333     setChildArmature: function (armature) {
334         if (this._childArmature !== armature) {
335             if (armature == null && this._childArmature)
336                 this._childArmature.setParentBone(null);
337             this._childArmature = armature;
338         }
339     },
340 
341     /**
342      * Returns ccs.Bone's child armature.
343      * @return {ccs.Armature}
344      */
345     getChildArmature: function () {
346         return this._childArmature;
347     },
348 
349     /**
350      * Return the tween of ccs.Bone
351      * @return {ccs.Tween}
352      */
353     getTween: function () {
354         return this._tween;
355     },
356 
357     /**
358      * Sets the local zOrder to ccs.Bone.
359      * @param {Number} zOrder
360      */
361     setLocalZOrder: function (zOrder) {
362         if (this._localZOrder !== zOrder)
363             cc.Node.prototype.setLocalZOrder.call(this, zOrder);
364     },
365 
366     /**
367      * Return the worldTransform of ccs.Bone.
368      * @returns {cc.AffineTransform}
369      */
370     getNodeToArmatureTransform: function(){
371         return this._worldTransform;
372     },
373 
374     /**
375      * Returns the world transform of ccs.Bone.
376      * @override
377      * @returns {cc.AffineTransform}
378      */
379     getNodeToWorldTransform: function(){
380         return cc.affineTransformConcat(this._worldTransform, this._armature.getNodeToWorldTransform());
381     },
382 
383     /**
384      * Returns the display render node.
385      * @returns {cc.Node}
386      */
387     getDisplayRenderNode: function () {
388         return this._displayManager.getDisplayRenderNode();
389     },
390 
391     /**
392      * Returns the type of display render node
393      * @returns {Number}
394      */
395     getDisplayRenderNodeType: function () {
396         return this._displayManager.getDisplayRenderNodeType();
397     },
398 
399     /**
400      * Add display and use  _displayData init the display.
401      * If index already have a display, then replace it.
402      * If index is current display index, then also change display to _index
403      * @param {ccs.DisplayData} displayData it include the display information, like DisplayType.
404      *          If you want to create a sprite display, then create a CCSpriteDisplayData param
405      *@param {Number}    index the index of the display you want to replace or add to
406      *          -1 : append display from back
407      */
408     addDisplay: function (displayData, index) {
409         index = index || 0;
410         return this._displayManager.addDisplay(displayData, index);
411     },
412 
413     /**
414      * Removes display by index.
415      * @param {Number} index display renderer's index
416      */
417     removeDisplay: function (index) {
418         this._displayManager.removeDisplay(index);
419     },
420 
421     /**
422      * Changes display by index
423      * @deprecated since v3.0, please use changeDisplayWithIndex instead.
424      * @param {Number} index
425      * @param {Boolean} force
426      */
427     changeDisplayByIndex: function (index, force) {
428         cc.log("changeDisplayByIndex is deprecated. Use changeDisplayWithIndex instead.");
429         this.changeDisplayWithIndex(index, force);
430     },
431 
432     /**
433      * Changes display by name
434      * @deprecated since v3.0, please use changeDisplayWithName instead.
435      * @param {String} name
436      * @param {Boolean} force
437      */
438     changeDisplayByName: function(name, force){
439         cc.log("changeDisplayByName is deprecated. Use changeDisplayWithName instead.");
440         this.changeDisplayWithName(name, force);
441     },
442 
443     /**
444      * Changes display with index
445      * @param {Number} index
446      * @param {Boolean} force
447      */
448     changeDisplayWithIndex: function (index, force) {
449         this._displayManager.changeDisplayWithIndex(index, force);
450     },
451 
452     /**
453      * Changes display with name
454      * @param {String} name
455      * @param {Boolean} force
456      */
457     changeDisplayWithName: function (name, force) {
458         this._displayManager.changeDisplayWithName(name, force);
459     },
460 
461     /**
462      * Returns the collide detector of ccs.Bone.
463      * @returns {*}
464      */
465     getColliderDetector: function(){
466         var decoDisplay = this._displayManager.getCurrentDecorativeDisplay();
467         if (decoDisplay){
468             var detector = decoDisplay.getColliderDetector();
469             if (detector)
470                 return detector;
471         }
472         return null;
473     },
474 
475     /**
476      * Sets collider filter to ccs.Bone.
477      * @param {ccs.ColliderFilter} filter
478      */
479     setColliderFilter: function (filter) {
480         var displayList = this._displayManager.getDecorativeDisplayList();
481         for (var i = 0; i < displayList.length; i++) {
482             var locDecoDisplay = displayList[i];
483             var locDetector = locDecoDisplay.getColliderDetector();
484             if (locDetector)
485                 locDetector.setColliderFilter(filter);
486         }
487     },
488 
489     /**
490      * Returns collider filter of ccs.Bone.
491      * @returns {cc.ColliderFilter}
492      */
493     getColliderFilter: function () {
494         var decoDisplay = this.displayManager.getCurrentDecorativeDisplay();
495         if (decoDisplay) {
496             var detector = decoDisplay.getColliderDetector();
497             if (detector)
498                 return detector.getColliderFilter();
499         }
500         return null;
501     },
502 
503     /**
504      * Sets ccs.Bone's transform dirty flag.
505      * @param {Boolean} dirty
506      */
507     setTransformDirty: function (dirty) {
508         this._boneTransformDirty = dirty;
509     },
510 
511     /**
512      * Returns ccs.Bone's transform dirty flag whether is dirty.
513      * @return {Boolean}
514      */
515     isTransformDirty: function () {
516         return this._boneTransformDirty;
517     },
518 
519     /**
520      * displayManager dirty getter
521      * @return {ccs.DisplayManager}
522      */
523     getDisplayManager: function () {
524         return this._displayManager;
525     },
526 
527     /**
528      *    When CCArmature play a animation, if there is not a CCMovementBoneData of this bone in this CCMovementData, this bone will hide.   <br/>
529      *    Set IgnoreMovementBoneData to true, then this bone will also show.
530      * @param {Boolean} bool
531      */
532     setIgnoreMovementBoneData: function (bool) {
533         this._ignoreMovementBoneData = bool;
534     },
535 
536     /**
537      * Returns whether is ignore movement bone data.
538      * @returns {Boolean}
539      */
540     isIgnoreMovementBoneData: function(){
541         return this._ignoreMovementBoneData;
542     },
543 
544     /**
545      * Returns the blendFunc of ccs.Bone.
546      * @return {cc.BlendFunc}
547      */
548     getBlendFunc: function () {
549         return new cc.BlendFunc(this._blendFunc.src, this._blendFunc.dst);
550     },
551 
552     /**
553      * Sets blend dirty flag
554      * @param {Boolean} dirty
555      */
556     setBlendDirty: function (dirty) {
557         this._blendDirty = dirty;
558     },
559 
560     /**
561      * Returns the blend dirty flag whether is dirty.
562      * @returns {Boolean|*|ccs.Bone._blendDirty}
563      */
564     isBlendDirty: function () {
565         return this._blendDirty;
566     },
567 
568     /**
569      * Returns the tweenData of ccs.Bone.
570      * @return {ccs.FrameData}
571      */
572     getTweenData: function () {
573         return this._tweenData;
574     },
575 
576     /**
577      * Returns the world information of ccs.Bone.
578      * @returns {ccs.BaseData}
579      */
580     getWorldInfo: function(){
581         return this._worldInfo;
582     },
583 
584     /**
585      * Returns the children of ccs.Bone
586      * @return {Array}
587      * @deprecated since v3.0, please use getChildren instead.
588      */
589     getChildrenBone: function () {
590         return this._children;
591     },
592 
593     /**
594      * Returns the worldTransform of ccs.Bone.
595      * @return {cc.AffineTransform}
596      * @deprecated since v3.0, please use getNodeToArmatureTransform instead.
597      */
598     nodeToArmatureTransform: function () {
599         return this.getNodeToArmatureTransform();
600     },
601 
602     /**
603      * @deprecated
604      * Returns the world affine transform matrix. The matrix is in Pixels.
605      * @returns {cc.AffineTransform}
606      */
607     nodeToWorldTransform: function () {
608         return this.getNodeToWorldTransform();
609     },
610 
611     /**
612      * Returns the collider body list in this bone.
613      * @returns {Array|null}
614      * @deprecated since v3.0, please use getColliderDetector to get a delector, and calls its getColliderBodyList instead.
615      */
616     getColliderBodyList: function () {
617         var detector = this.getColliderDetector();
618         if(detector)
619             return detector.getColliderBodyList();
620         return null;
621     },
622 
623     /**
624      * Returns whether is ignore movement bone data.
625      * @return {Boolean}
626      * @deprecated since v3.0, please isIgnoreMovementBoneData instead.
627      */
628     getIgnoreMovementBoneData: function () {
629         return this.isIgnoreMovementBoneData();
630     },
631 
632     _createRenderCmd: function(){
633         if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
634             return new ccs.Bone.CanvasRenderCmd(this);
635         else
636             return new ccs.Bone.WebGLRenderCmd(this);
637     }
638 });
639 
640 var _p = ccs.Bone.prototype;
641 
642 // Extended properties
643 /** @expose */
644 _p.boneData;
645 cc.defineGetterSetter(_p, "boneData", _p.getBoneData, _p.setBoneData);
646 /** @expose */
647 _p.armature;
648 cc.defineGetterSetter(_p, "armature", _p.getArmature, _p.setArmature);
649 /** @expose */
650 _p.childArmature;
651 cc.defineGetterSetter(_p, "childArmature", _p.getChildArmature, _p.setChildArmature);
652 /** @expose */
653 _p.childrenBone;
654 cc.defineGetterSetter(_p, "childrenBone", _p.getChildrenBone);
655 /** @expose */
656 _p.tween;
657 cc.defineGetterSetter(_p, "tween", _p.getTween);
658 /** @expose */
659 _p.tweenData;
660 cc.defineGetterSetter(_p, "tweenData", _p.getTweenData);
661 /** @expose */
662 _p.colliderFilter;
663 cc.defineGetterSetter(_p, "colliderFilter", _p.getColliderFilter, _p.setColliderFilter);
664 
665 _p = null;
666 
667 /**
668  * Allocates and initializes a bone.
669  * @return {ccs.Bone}
670  * @deprecated since v3.1, please use new construction instead
671  */
672 ccs.Bone.create = function (name) {
673     return new ccs.Bone(name);
674 };
675 
676 ccs.Bone.RenderCmd = {
677     _updateColor: function () {
678         var node = this._node;
679         var display = node._displayManager.getDisplayRenderNode();
680         if (display !== null) {
681             var displayCmd = display._renderCmd;
682             display.setColor(this._displayedColor);
683             display.setOpacity(this._displayedOpacity);
684             displayCmd._syncDisplayColor(node._tweenData);
685             displayCmd._syncDisplayOpacity(node._tweenData.a);
686             displayCmd._updateColor();
687         }
688     },
689 
690     transform: function (parentCmd, recursive) {
691         var node = this._node,
692             t = this._transform,
693             wt = this._worldTransform,
694             pt = parentCmd ? parentCmd._worldTransform : null;
695 
696         if (pt) {
697             this.originTransform();
698             cc.affineTransformConcatIn(t, node._worldTransform);
699         }
700 
701         if (pt) {
702             wt.a  = t.a  * pt.a + t.b  * pt.c;
703             wt.b  = t.a  * pt.b + t.b  * pt.d;
704             wt.c  = t.c  * pt.a + t.d  * pt.c;
705             wt.d  = t.c  * pt.b + t.d  * pt.d;
706             wt.tx = t.tx * pt.a + t.ty * pt.c + pt.tx;
707             wt.ty = t.tx * pt.b + t.ty * pt.d + pt.ty;
708         }
709         else {
710             wt.a  = t.a;
711             wt.b  = t.b;
712             wt.c  = t.c;
713             wt.d  = t.d;
714             wt.tx = t.tx;
715             wt.ty = t.ty;
716         }
717     }
718 };
719 
720 (function(){
721     ccs.Bone.CanvasRenderCmd  = function(renderable){
722         cc.Node.CanvasRenderCmd.call(this, renderable);
723         this._needDraw = false;
724     };
725 
726     var proto = ccs.Bone.CanvasRenderCmd.prototype = Object.create(cc.Node.CanvasRenderCmd.prototype);
727     cc.inject(ccs.Bone.RenderCmd, proto);
728     proto.constructor = ccs.Bone.CanvasRenderCmd;
729 })();
730 
731 (function(){
732     if(!cc.Node.WebGLRenderCmd)
733         return;
734     ccs.Bone.WebGLRenderCmd = function(renderable){
735         cc.Node.WebGLRenderCmd.call(this, renderable);
736         this._needDraw = false;
737     };
738 
739     var proto = ccs.Bone.WebGLRenderCmd.prototype = Object.create(cc.Node.WebGLRenderCmd.prototype);
740     cc.inject(ccs.Bone.RenderCmd, proto);
741     proto.constructor = ccs.Bone.WebGLRenderCmd;
742 })();
743