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  * ccs.Bone uses ccs.Skin to displays on screen.
 28  * @class
 29  * @extends ccs.Sprite
 30  *
 31  * @property {Object}   skinData    - The data of the skin
 32  * @property {ccs.Bone} bone        - The bone of the skin
 33  * @property {String}   displayName - <@readonly> The displayed name of skin
 34  *
 35  */
 36 ccs.Skin = ccs.Sprite.extend(/** @lends ccs.Skin# */{
 37     _skinData: null,
 38     bone: null,
 39     _skinTransform: null,
 40     _displayName: "",
 41     _armature: null,
 42     _className: "Skin",
 43 
 44     ctor: function () {
 45         cc.Sprite.prototype.ctor.call(this);
 46         this._skinData = null;
 47         this.bone = null;
 48         this._displayName = "";
 49         this._skinTransform = cc.affineTransformIdentity();
 50         this._armature = null;
 51     },
 52 
 53     initWithSpriteFrameName: function (spriteFrameName) {
 54         if(spriteFrameName == "")
 55             return false;
 56         var pFrame = cc.spriteFrameCache.getSpriteFrame(spriteFrameName);
 57         var ret = true;
 58         if(pFrame)
 59             this.initWithSpriteFrame(pFrame);
 60         else{
 61             cc.log("Can't find CCSpriteFrame with %s. Please check your .plist file", spriteFrameName);
 62             ret = false;
 63         }
 64         this._displayName = spriteFrameName;
 65         return ret;
 66     },
 67 
 68     initWithFile: function (fileName) {
 69         var ret = cc.Sprite.prototype.initWithFile.call(this, fileName);
 70         this._displayName = fileName;
 71         return ret;
 72     },
 73 
 74     setSkinData: function (skinData) {
 75         this._skinData = skinData;
 76         this.setScaleX(skinData.scaleX);
 77         this.setScaleY(skinData.scaleY);
 78         this.setRotationX(cc.radiansToDegrees(skinData.skewX));
 79         this.setRotationY(cc.radiansToDegrees(-skinData.skewY));
 80         this.setPosition(skinData.x, skinData.y);
 81 
 82         var localTransform = this.getNodeToParentTransform ? this.getNodeToParentTransform() : this.nodeToParentTransform();
 83         var skinTransform = this._skinTransform;
 84         skinTransform.a = localTransform.a;
 85         skinTransform.b = localTransform.b;
 86         skinTransform.c = localTransform.c;
 87         skinTransform.d = localTransform.d;
 88         skinTransform.tx = localTransform.tx;
 89         skinTransform.ty = localTransform.ty;
 90         this.updateArmatureTransform();
 91     },
 92 
 93     getSkinData: function () {
 94         return this._skinData;
 95     },
 96 
 97     updateArmatureTransform: function () {
 98         this._transform = cc.affineTransformConcat(
 99             this._skinTransform,
100             this.bone.getNodeToArmatureTransform()
101         );
102     },
103 
104     _updateTransformForWebGL: function(){
105         var locQuad = this._quad;
106         // If it is not visible, or one of its ancestors is not visible, then do nothing:
107         if( !this._visible)
108             locQuad.br.vertices = locQuad.tl.vertices = locQuad.tr.vertices = locQuad.bl.vertices = {x: 0, y:0, z:0};
109         else {
110             //
111             // calculate the Quad based on the Affine Matrix
112             //
113             var transform = this.getNodeToParentTransform ? this.getNodeToParentTransform() : this.nodeToParentTransform();
114             var size = this._rect;
115 
116             var x1 = this._offsetPosition.x, y1 = this._offsetPosition.y;
117 
118             var x2 = x1 + size.width, y2 = y1 + size.height;
119             var x = transform.tx, y = transform.ty;
120 
121             var cr = transform.a, sr = transform.b;
122             var cr2 = transform.d, sr2 = -transform.c;
123             var ax = x1 * cr - y1 * sr2 + x;
124             var ay = x1 * sr + y1 * cr2 + y;
125 
126             var bx = x2 * cr - y1 * sr2 + x;
127             var by = x2 * sr + y1 * cr2 + y;
128 
129             var cx = x2 * cr - y2 * sr2 + x;
130             var cy = x2 * sr + y2 * cr2 + y;
131 
132             var dx = x1 * cr - y2 * sr2 + x;
133             var dy = x1 * sr + y2 * cr2 + y;
134 
135             var locVertexZ = this._vertexZ;
136             if(!cc.SPRITEBATCHNODE_RENDER_SUBPIXEL) {
137                 ax = 0 | ax;
138                 ay = 0 | ay;
139                 bx = 0 | bx;
140                 by = 0 | by;
141                 cx = 0 | cx;
142                 cy = 0 | cy;
143                 dx = 0 | dx;
144                 dy = 0 | dy;
145             }
146             this.SET_VERTEX3F(locQuad.bl.vertices,ax, ay,locVertexZ);
147             this.SET_VERTEX3F(locQuad.br.vertices,bx, by,locVertexZ);
148             this.SET_VERTEX3F(locQuad.tl.vertices,dx, dy,locVertexZ);
149             this.SET_VERTEX3F(locQuad.tr.vertices,cx, cy,locVertexZ);
150         }
151 
152         // MARMALADE CHANGE: ADDED CHECK FOR nullptr, TO PERMIT SPRITES WITH NO BATCH NODE / TEXTURE ATLAS
153         if (this._textureAtlas)
154             this._textureAtlas.updateQuad(locQuad, this._textureAtlas.getTotalQuads());
155         this._quadDirty = true;
156     },
157 
158     SET_VERTEX3F: function(_v_, _x_, _y_, _z_){
159         (_v_).x = (_x_);
160         (_v_).y = (_y_);
161         (_v_).z = (_z_);
162     },
163 
164     RENDER_IN_SUBPIXEL: function(__ARGS__){
165         if(!cc.SPRITEBATCHNODE_RENDER_SUBPIXEL)
166             return Math.ceil(__ARGS__);
167         else
168             return __ARGS__;
169     },
170 
171     getNodeToWorldTransform: function(){
172         return cc.affineTransformConcat(this._transform,this.bone.getArmature().getNodeToWorldTransform());
173     },
174 
175     getNodeToWorldTransformAR: function(){
176         var displayTransform = this._transform;
177         this._anchorPointInPoints = cc.pointApplyAffineTransform(this._anchorPointInPoints, displayTransform);
178         displayTransform.tx = this._anchorPointInPoints.x;
179         displayTransform.ty = this._anchorPointInPoints.y;
180         return cc.affineTransformConcat( displayTransform,this.bone.getArmature().nodeToWorldTransform());
181     },
182 
183     setBone: function (bone) {
184         this.bone = bone;
185         var armature = this.bone.getArmature();
186         if(armature)
187             this._armature = armature;
188     },
189 
190     getBone: function () {
191         return this.bone;
192     },
193 
194     /**
195      * display name getter
196      * @returns {String}
197      */
198     getDisplayName: function () {
199         return this._displayName;
200     }
201 });
202 if (cc._renderType == cc._RENDER_TYPE_WEBGL) {
203     ccs.Skin.prototype.updateTransform = ccs.Skin.prototype._updateTransformForWebGL;
204 }else{
205     //ccs.Skin.prototype.getNodeToParentTransform = cc.Node.prototype._getNodeToParentTransformForWebGL;
206 }
207 //ccs.Skin.prototype.nodeToParentTransform = cc.Node.prototype._getNodeToParentTransformForWebGL;
208 
209 
210 var _p = ccs.Skin.prototype;
211 
212 // Extended properties
213 /** @expose */
214 _p.skinData;
215 cc.defineGetterSetter(_p, "skinData", _p.getSkinData, _p.setSkinData);
216 /** @expose */
217 _p.displayName;
218 cc.defineGetterSetter(_p, "displayName", _p.getDisplayName);
219 
220 _p = null;
221 
222 /**
223  * allocates and initializes a skin.
224  * @param {String} [fileName] fileName or sprite frame name
225  * @param {cc.Rect} [rect]
226  * @returns {ccs.Skin}
227  * @example
228  * // example
229  * var skin = ccs.Skin.create("res/test.png",cc.rect(0,0,50,50));
230  * var skin = ccs.Skin.create("#test.png");             //=> ccs.Skin.createWithSpriteFrameName("test.png");
231  */
232 ccs.Skin.create = function (fileName, rect) {
233     var argnum = arguments.length;
234     var skin = new ccs.Skin();
235     if (argnum === 0 || fileName == null || fileName == "") {
236         if (skin.init())
237             return skin;
238     } else {
239         if(fileName[0] == "#"){
240             if (skin && skin.initWithSpriteFrameName(fileName))
241                 return skin;
242         }else{
243             if (skin && skin.initWithFile(fileName, rect))
244                 return skin;
245         }
246     }
247     return null;
248 };
249 
250 /**
251  * allocates and initializes a skin.
252  * @param {String} spriteFrameName
253  * @returns {ccs.Skin}
254  * @example
255  * // example
256  * var skin = ccs.Skin.createWithSpriteFrameName("test.png");
257  */
258 ccs.Skin.createWithSpriteFrameName = function (spriteFrameName) {
259     var skin = new ccs.Skin();
260     if (skin && skin.initWithSpriteFrameName(spriteFrameName))
261         return skin;
262     return null;
263 };
264