1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 28 /** <p> cc.AtlasNode is a subclass of cc.Node that implements the cc.RGBAProtocol and<br/> 29 * cc.TextureProtocol protocol</p> 30 * 31 * <p> It knows how to render a TextureAtlas object. <br/> 32 * If you are going to render a TextureAtlas consider subclassing cc.AtlasNode (or a subclass of cc.AtlasNode)</p> 33 * 34 * <p> All features from cc.Node are valid, plus the following features: <br/> 35 * - opacity and RGB colors </p> 36 * @class 37 * @extends cc.Node 38 */ 39 cc.AtlasNode = cc.Node.extend(/** @lends cc.AtlasNode# */{ 40 RGBAProtocol:true, 41 //! chars per row 42 _itemsPerRow:0, 43 //! chars per column 44 _itemsPerColumn:0, 45 //! width of each char 46 _itemWidth:0, 47 //! height of each char 48 _itemHeight:0, 49 _colorUnmodified:cc.c3b(0, 0, 0), 50 _textureAtlas:null, 51 // protocol variables 52 _isOpacityModifyRGB:false, 53 _blendFunc: {src:cc.BLEND_SRC, dst:cc.BLEND_DST}, 54 _opacity:0, 55 _color:null, 56 _originalTexture:null, 57 // quads to draw 58 _quadsToDraw:0, 59 _uniformColor:0, 60 61 /** initializes an cc.AtlasNode with an Atlas file the width and height of each item and the quantity of items to render 62 * @param {String} tile 63 * @param {Number} tileWidth 64 * @param {Number} tileHeight 65 * @param {Number} itemsToRender 66 * @return {Boolean} 67 */ 68 initWithTileFile:function (tile, tileWidth, tileHeight, itemsToRender) { 69 cc.Assert(tile != null, "title should not be null"); 70 this._itemWidth = tileWidth; 71 this._itemHeight = tileHeight; 72 73 this._opacity = 255; 74 this._color = cc.white(); 75 this._colorUnmodified = cc.white(); 76 this._isOpacityModifyRGB = true; 77 78 this._blendFunc.src = cc.BLEND_SRC; 79 this._blendFunc.dst = cc.BLEND_DST; 80 81 var newAtlas = new cc.TextureAtlas(); 82 newAtlas.initWithFile(tile, itemsToRender); 83 this.setTextureAtlas(newAtlas); 84 85 if (cc.renderContextType == cc.CANVAS) { 86 this._originalTexture = this._textureAtlas.getTexture(); 87 } 88 89 if (!this._textureAtlas) { 90 cc.log("cocos2d: Could not initialize cc.AtlasNode. Invalid Texture."); 91 return false; 92 } 93 94 this._updateBlendFunc(); 95 this._updateOpacityModifyRGB(); 96 97 this._calculateMaxItems(); 98 99 this._quadsToDraw = itemsToRender; 100 101 //shader stuff 102 //this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(kCCShader_PositionTexture_uColor)); 103 //this._uniformColor = glGetUniformLocation( this.getShaderProgram().getProgram(), "u_color"); 104 105 return true; 106 107 }, 108 109 /** updates the Atlas (indexed vertex array). 110 * Shall be overriden in subclasses 111 */ 112 updateAtlasValues:function () { 113 cc.Assert(false, "cc.AtlasNode:Abstract updateAtlasValue not overriden"); 114 }, 115 116 /** 117 * @param {CanvasContext} ctx CanvasContext 118 */ 119 draw:function (ctx) { 120 this._super(); 121 if (cc.renderContextType == cc.CANVAS) { 122 123 } else { 124 //TODO for WebGL 125 //cc.NODE_DRAW_SETUP(); 126 127 //ccGLBlendFunc( this._blendFunc.src, this._blendFunc.dst ); 128 129 //var colors = [this._color.r / 255.0, this._color.g / 255.0, this._color.b / 255.0, this._opacity / 255.0]; 130 //this.getShaderProgram().setUniformLocationWith4fv(this._uniformColor, colors, 1); 131 132 //this._textureAtlas.drawNumberOfQuads(this._quadsToDraw, 0); 133 } 134 }, 135 136 /** cc.AtlasNode - RGBA protocol 137 * @return {cc.Color3B} 138 */ 139 getColor:function () { 140 if (this._isOpacityModifyRGB) { 141 return this._colorUnmodified; 142 } 143 return this._color; 144 }, 145 146 /** 147 * @param {cc.Color3B} color3 148 */ 149 setColor:function (color3) { 150 if ((this._color.r == color3.r) && (this._color.g == color3.g) && (this._color.b == color3.b)) { 151 return; 152 } 153 this._color = this._colorUnmodified = color3; 154 155 if (this.getTexture()) { 156 if (cc.renderContextType == cc.CANVAS) { 157 var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(this._originalTexture); 158 if (cacheTextureForColor) { 159 var tx = this._originalTexture; 160 var textureRect = cc.rect(0, 0, tx.width, tx.height); 161 var colorTexture = cc.generateTintImage(tx, cacheTextureForColor, this._color, textureRect); 162 var img = new Image(); 163 img.src = colorTexture.toDataURL(); 164 this.setTexture(img); 165 } 166 } 167 } 168 169 if (this._isOpacityModifyRGB) { 170 this._color.r = color3.r * this._opacity / 255; 171 this._color.g = color3.g * this._opacity / 255; 172 this._color.b = color3.b * this._opacity / 255; 173 } 174 }, 175 176 /** 177 * @return {Number} 178 */ 179 getOpacity:function () { 180 return this._opacity; 181 }, 182 183 /** 184 * @param {Number} opacity 185 */ 186 setOpacity:function (opacity) { 187 this._opacity = opacity; 188 // special opacity for premultiplied textures 189 //if (this._isOpacityModifyRGB) { 190 // this.setColor(this._colorUnmodified); 191 //} 192 }, 193 194 /** 195 * @param {Boolean} value 196 */ 197 setOpacityModifyRGB:function (value) { 198 var oldColor = this._color; 199 this._isOpacityModifyRGB = value; 200 this._color = oldColor; 201 }, 202 203 /** 204 * @return {Boolean} 205 */ 206 isOpacityModifyRGB:function () { 207 return this._isOpacityModifyRGB; 208 }, 209 210 /** cc.AtlasNode - CocosNodeTexture protocol 211 * @return {cc.BlendFunc} 212 */ 213 getBlendFunc:function () { 214 return this._blendFunc; 215 }, 216 217 /** 218 * @param {cc.BlendFunc} blendFunc 219 */ 220 setBlendFunc:function (src, dst) { 221 if(arguments.length == 1) 222 this._blendFunc = src; 223 else 224 this._blendFunc = {src:src, dst:dst}; 225 }, 226 227 // cc.Texture protocol 228 229 /** returns the used texture 230 * @return {cc.Texture2D} 231 */ 232 getTexture:function () { 233 return this._textureAtlas.getTexture(); 234 }, 235 236 /** sets a new texture. it will be retained 237 * @param {cc.Texture2D} texture 238 */ 239 setTexture:function (texture) { 240 this._textureAtlas.setTexture(texture); 241 this._updateBlendFunc(); 242 this._updateOpacityModifyRGB(); 243 }, 244 245 /** 246 * @param {cc.TextureAtlas} value 247 */ 248 setTextureAtlas:function (value) { 249 this._textureAtlas = value; 250 }, 251 252 /** 253 * @return {cc.TextureAtlas} 254 */ 255 getTextureAtlas:function () { 256 return this._textureAtlas; 257 }, 258 259 /** 260 * @return {Number} 261 */ 262 getQuadsToDraw:function () { 263 return this._quadsToDraw; 264 }, 265 266 /** 267 * @param {Number} quadsToDraw 268 */ 269 setQuadsToDraw:function (quadsToDraw) { 270 this._quadsToDraw = quadsToDraw; 271 }, 272 273 _calculateMaxItems:function () { 274 var size; 275 if (this._textureAtlas.getTexture() instanceof cc.Texture2D) { 276 size = this._textureAtlas.getTexture().getContentSize(); 277 } 278 else { 279 size = cc.size(this._textureAtlas.getTexture().width, this._textureAtlas.getTexture().height); 280 } 281 this._itemsPerColumn = parseInt(size.height / this._itemHeight); 282 this._itemsPerRow = parseInt(size.width / this._itemWidth); 283 }, 284 285 _updateBlendFunc:function () { 286 /* if (!this._textureAtlas.getTexture().hasPremultipliedAlpha()) { 287 this._blendFunc.src = gl.SRC_ALPHA; 288 this._blendFunc.dst = gl.ONE_MINUS_SRC_ALPHA; 289 }*/ 290 }, 291 292 _updateOpacityModifyRGB:function () { 293 //this._isOpacityModifyRGB = this._textureAtlas.getTexture().hasPremultipliedAlpha(); 294 } 295 296 }); 297 298 /** creates a cc.AtlasNode with an Atlas file the width and height of each item and the quantity of items to render 299 * @param {String} tile 300 * @param {Number} tileWidth 301 * @param {Number} tileHeight 302 * @param {Number} itemsToRender 303 * @return {cc.AtlasNode} 304 * @example 305 * // example 306 * var node = cc.AtlasNode.create("pathOfTile", 16, 16, 1); 307 */ 308 cc.AtlasNode.create = function (tile, tileWidth, tileHeight, itemsToRender) { 309 var ret = new cc.AtlasNode(); 310 if (ret.initWithTileFile(tile, tileWidth, tileHeight, itemsToRender)) { 311 return ret; 312 } 313 return null; 314 }; 315