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