/**************************************************************************** Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2008-2010 Ricardo Quesada Copyright (c) 2011 Zynga Inc. http://www.cocos2d-x.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ /** * cc.Sprite invalid index on the cc.SpriteBatchNode * @constant * @type Number */ cc.SPRITE_INDEX_NOT_INITIALIZED = -1; /** * generate texture's cache for texture tint * @function * @param {HTMLImageElement} texture * @return {Array} */ cc.generateTextureCacheForColor = function (texture) { if (texture.channelCache) { return texture.channelCache; } var textureCache = [ document.createElement("canvas"), document.createElement("canvas"), document.createElement("canvas"), document.createElement("canvas") ]; function renderToCache() { var ref = cc.generateTextureCacheForColor; var w = texture.width; var h = texture.height; textureCache[0].width = w; textureCache[0].height = h; textureCache[1].width = w; textureCache[1].height = h; textureCache[2].width = w; textureCache[2].height = h; textureCache[3].width = w; textureCache[3].height = h; ref.canvas.width = w; ref.canvas.height = h; var ctx = ref.canvas.getContext("2d"); ctx.drawImage(texture, 0, 0); ref.tempCanvas.width = w; ref.tempCanvas.height = h; var pixels = ctx.getImageData(0, 0, w, h).data; for (var rgbI = 0; rgbI < 4; rgbI++) { var cacheCtx = textureCache[rgbI].getContext('2d'); cacheCtx.getImageData(0, 0, w, h).data; ref.tempCtx.drawImage(texture, 0, 0); var to = ref.tempCtx.getImageData(0, 0, w, h); var toData = to.data; for (var i = 0; i < pixels.length; i += 4) { toData[i ] = (rgbI === 0) ? pixels[i ] : 0; toData[i + 1] = (rgbI === 1) ? pixels[i + 1] : 0; toData[i + 2] = (rgbI === 2) ? pixels[i + 2] : 0; toData[i + 3] = pixels[i + 3]; } cacheCtx.putImageData(to, 0, 0); } texture.onload = null; } try { renderToCache(); } catch (e) { texture.onload = renderToCache; } texture.channelCache = textureCache; return textureCache; }; cc.generateTextureCacheForColor.canvas = document.createElement('canvas'); cc.generateTextureCacheForColor.tempCanvas = document.createElement('canvas'); cc.generateTextureCacheForColor.tempCtx = cc.generateTextureCacheForColor.tempCanvas.getContext('2d'); /** * generate tinted texture * source-in: Where source and destination overlaps and both are opaque, the source is displayed. * Everywhere else transparency is displayed. * @function * @param {HTMLImageElement} texture * @param {cc.Color3B|cc.Color4F} color * @param {cc.Rect} rect * @return {HTMLCanvasElement} */ cc.generateTintImage2 = function (texture, color, rect) { if (!rect) { rect = cc.rect(0, 0, texture.width, texture.height); rect = cc.RECT_PIXELS_TO_POINTS(rect); } var selColor; if (color instanceof cc.Color4F) { selColor = cc.c4b(color.r * 255, color.g * 255, color.b * 255, color.a * 255); } else { selColor = cc.c4b(color.r, color.g, color.b, 50);//color; } var buff = document.createElement("canvas"); var ctx = buff.getContext("2d"); if (buff.width != rect.width) buff.width = rect.width; if (buff.height != rect.height) buff.height = rect.height; ctx.save(); ctx.drawImage(texture, rect.x, rect.y, rect.width, rect.height, 0, 0, rect.width, rect.height); ctx.globalCompositeOperation = "source-in"; ctx.globalAlpha = selColor.a / 255.0; ctx.fillStyle = "rgb(" + selColor.r + "," + selColor.g + "," + selColor.b + ")"; ctx.fillRect(0, 0, rect.width, rect.height); ctx.restore(); return buff; }; /** * generate tinted texture * lighter: The source and destination colors are added to each other, resulting in brighter colors, * moving towards color values of 1 (maximum brightness for that color). * @function * @param {HTMLImageElement} texture * @param {Array} tintedImgCache * @param {cc.Color3B|cc.Color4F} color * @param {cc.Rect} rect * @param {HTMLCanvasElement} [renderCanvas] * @return {HTMLCanvasElement} */ cc.generateTintImage = function (texture, tintedImgCache, color, rect, renderCanvas) { if (!rect) rect = cc.rect(0, 0, texture.width, texture.height); var selColor; if (color.a == null) { // Optimization for the particle system which mainly uses c4f colors selColor = cc.c4f(color.r / 255.0, color.g / 255.0, color.b / 255, 1); } else { selColor = color; } var w = Math.min(rect.width, tintedImgCache[0].width); var h = Math.min(rect.height, tintedImgCache[0].height); var buff = renderCanvas; var ctx; // Create a new buffer if required if (!buff) { buff = document.createElement("canvas"); buff.width = w; buff.height = h; ctx = buff.getContext("2d"); } else { ctx = buff.getContext("2d"); ctx.clearRect(0, 0, w, h); } ctx.save(); ctx.globalCompositeOperation = 'lighter'; // Make sure to keep the renderCanvas alpha in mind in case of overdraw var a = ctx.globalAlpha; if (selColor.r > 0) { ctx.globalAlpha = selColor.r * a; ctx.drawImage(tintedImgCache[0], rect.x, rect.y, w, h, 0, 0, w, h); } if (selColor.g > 0) { ctx.globalAlpha = selColor.g * a; ctx.drawImage(tintedImgCache[1], rect.x, rect.y, w, h, 0, 0, w, h); } if (selColor.b > 0) { ctx.globalAlpha = selColor.b * a; ctx.drawImage(tintedImgCache[2], rect.x, rect.y, w, h, 0, 0, w, h); } if (selColor.r + selColor.g + selColor.b < 1) { ctx.globalAlpha = a; ctx.drawImage(tintedImgCache[3], rect.x, rect.y, w, h, 0, 0, w, h); } ctx.restore(); return buff; }; cc.cutRotateImageToCanvas = function (texture, rect) { if (!texture) return null; if (!rect) return texture; var nCanvas = document.createElement("canvas"); nCanvas.width = rect.width; nCanvas.height = rect.height; var ctx = nCanvas.getContext("2d"); ctx.translate(nCanvas.width / 2, nCanvas.height / 2); ctx.rotate(-1.5707963267948966); ctx.drawImage(texture, rect.x, rect.y, rect.height, rect.width, -rect.height / 2, -rect.width / 2, rect.height, rect.width); return nCanvas; }; /** * a Values object for transform * @Class * @Construct * @param {cc.Point} pos position x and y * @param {cc.Point} scale scale x and y * @param {Number} rotation * @param {cc.Point} skew skew x and y * @param {cc.Point} ap anchor point in pixels * @param {Boolean} visible */ cc.TransformValues = function (pos, scale, rotation, skew, ap, visible) { this.pos = pos; // position x and y this.scale = scale; // scale x and y this.rotation = rotation; this.skew = skew; // skew x and y this.ap = ap; // anchor point in pixels this.visible = visible; }; cc.RENDER_IN_SUBPIXEL = function (A) { return (0 | A); }; if (cc.SPRITEBATCHNODE_RENDER_SUBPIXEL) { cc.RENDER_IN_SUBPIXEL = function (A) { return A; }; } /** *

cc.Sprite is a 2d image ( http://en.wikipedia.org/wiki/Sprite_(computer_graphics) )
* * cc.Sprite can be created with an image, or with a sub-rectangle of an image.
* * If the parent or any of its ancestors is a cc.SpriteBatchNode then the following features/limitations are valid
* - Features when the parent is a cc.BatchNode:
* - MUCH faster rendering, specially if the cc.SpriteBatchNode has many children. All the children will be drawn in a single batch.
* * - Limitations
* - Camera is not supported yet (eg: CCOrbitCamera action doesn't work)
* - GridBase actions are not supported (eg: CCLens, CCRipple, CCTwirl)
* - The Alias/Antialias property belongs to CCSpriteBatchNode, so you can't individually set the aliased property.
* - The Blending function property belongs to CCSpriteBatchNode, so you can't individually set the blending function property.
* - Parallax scroller is not supported, but can be simulated with a "proxy" sprite.
* * If the parent is an standard cc.Node, then cc.Sprite behaves like any other cc.Node:
* - It supports blending functions
* - It supports aliasing / antialiasing
* - But the rendering will be slower: 1 draw per children.
* * The default anchorPoint in cc.Sprite is (0.5, 0.5).

* @class * @extends cc.NodeRGBA * * @example * var aSprite = new cc.Sprite(); * aSprite.initWithFile("HelloHTML5World.png",cc.rect(0,0,480,320)); */ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ RGBAProtocol:true, // // Data used when the sprite is rendered using a CCSpriteSheet // _textureAtlas:null, //cc.SpriteBatchNode texture atlas _atlasIndex:0, _batchNode:null, _dirty:false, //Whether the sprite needs to be updated _recursiveDirty:null, //Whether all of the sprite's children needs to be updated _hasChildren:null, //Whether the sprite contains children _shouldBeHidden:false, //should not be drawn because one of the ancestors is not visible _transformToBatch:null, // // Data used when the sprite is self-rendered // _blendFunc:null, //It's required for CCTextureProtocol inheritance _texture:null, //cc.Texture2D object that is used to render the sprite // // Shared data // // texture _rect:null, //Retangle of cc.Texture2D _rectRotated:false, //Whether the texture is rotated // Offset Position (used by Zwoptex) _offsetPosition:null, // absolute _unflippedOffsetPositionFromCenter:null, _opacityModifyRGB:false, // image is flipped _flippedX:false, //Whether the sprite is flipped horizontally or not. _flippedY:false, //Whether the sprite is flipped vertically or not. _textureLoaded:false, _loadedEventListeners: null, _newTextureWhenChangeColor: null, //hack property for LabelBMFont textureLoaded:function(){ return this._textureLoaded; }, addLoadedEventListener:function(callback, target){ if(!this._loadedEventListeners) this._loadedEventListeners = []; this._loadedEventListeners.push({eventCallback:callback, eventTarget:target}); }, _callLoadedEventCallbacks:function(){ if(!this._loadedEventListeners) return; var locListeners = this._loadedEventListeners; for(var i = 0, len = locListeners.length; i < len; i++){ var selCallback = locListeners[i]; cc.doCallback(selCallback.eventCallback, selCallback.eventTarget, this); } locListeners.length = 0; }, /** * Whether or not the Sprite needs to be updated in the Atlas * @return {Boolean} true if the sprite needs to be updated in the Atlas, false otherwise. */ isDirty:function () { return this._dirty; }, /** * Makes the Sprite to be updated in the Atlas. * @param {Boolean} bDirty */ setDirty:function (bDirty) { this._dirty = bDirty; }, /** * Returns whether or not the texture rectangle is rotated. * @return {Boolean} */ isTextureRectRotated:function () { return this._rectRotated; }, /** * Returns the index used on the TextureAtlas. * @return {Number} */ getAtlasIndex:function () { return this._atlasIndex; }, /** * Set the index used on the TextureAtlas. * @warning Don't modify this value unless you know what you are doing * @param {Number} atlasIndex */ setAtlasIndex:function (atlasIndex) { this._atlasIndex = atlasIndex; }, /** * returns the rect of the cc.Sprite in points * @return {cc.Rect} */ getTextureRect:function () { return cc.rect(this._rect.x, this._rect.y, this._rect.width, this._rect.height); }, /** * Gets the weak reference of the cc.TextureAtlas when the sprite is rendered using via cc.SpriteBatchNode * @return {cc.TextureAtlas} */ getTextureAtlas:function () { return this._textureAtlas; }, /** * Sets the weak reference of the cc.TextureAtlas when the sprite is rendered using via cc.SpriteBatchNode * @param {cc.TextureAtlas} textureAtlas */ setTextureAtlas:function (textureAtlas) { this._textureAtlas = textureAtlas; }, /** * return the SpriteBatchNode of the cc.Sprite * @return {cc.SpriteBatchNode} */ getSpriteBatchNode:function () { return this._batchNode; }, /** * set the SpriteBatchNode of the cc.Sprite * @param {cc.SpriteBatchNode} spriteBatchNode */ setSpriteBatchNode:function (spriteBatchNode) { this._batchNode = spriteBatchNode; }, /** * Gets the offset position of the sprite. Calculated automatically by editors like Zwoptex. * @return {cc.Point} */ getOffsetPosition:function () { return cc.p(this._offsetPosition); }, /** * conforms to cc.TextureProtocol protocol * @return {cc.BlendFunc} */ getBlendFunc:function () { return this._blendFunc; }, /** * Initializes a sprite with an SpriteFrame. The texture and rect in SpriteFrame will be applied on this sprite * @param {cc.SpriteFrame} spriteFrame A CCSpriteFrame object. It should includes a valid texture and a rect * @return {Boolean} true if the sprite is initialized properly, false otherwise. * @example * var spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame("grossini_dance_01.png"); * var sprite = new cc.Sprite(); * sprite.initWithSpriteFrame(spriteFrame); */ initWithSpriteFrame:function (spriteFrame) { if(!spriteFrame) throw "cc.Sprite.initWithSpriteFrame(): spriteFrame should be non-null"; if(!spriteFrame.textureLoaded()){ //add event listener this._textureLoaded = false; spriteFrame.addLoadedEventListener(this._spriteFrameLoadedCallback, this); } var ret = this.initWithTexture(spriteFrame.getTexture(), spriteFrame.getRect()); this.setDisplayFrame(spriteFrame); return ret; }, _spriteFrameLoadedCallback:null, _spriteFrameLoadedCallbackForWebGL:function(spriteFrame){ this.setNodeDirty(); this.setTextureRect(spriteFrame.getRect(), spriteFrame.isRotated(), spriteFrame.getOriginalSize()); this._callLoadedEventCallbacks(); }, _spriteFrameLoadedCallbackForCanvas:function(spriteFrame){ this.setNodeDirty(); this.setTextureRect(spriteFrame.getRect(), spriteFrame.isRotated(), spriteFrame.getOriginalSize()); var curColor = this.getColor(); if (curColor.r !== 255 || curColor.g !== 255 || curColor.b !== 255) this._changeTextureColor(); this._callLoadedEventCallbacks(); }, /** * Initializes a sprite with a sprite frame name.
* A cc.SpriteFrame will be fetched from the cc.SpriteFrameCache by name.
* If the cc.SpriteFrame doesn't exist it will raise an exception.
* @param {String} spriteFrameName A key string that can fected a volid cc.SpriteFrame from cc.SpriteFrameCache * @return {Boolean} true if the sprite is initialized properly, false otherwise. * @example * var sprite = new cc.Sprite(); * sprite.initWithSpriteFrameName("grossini_dance_01.png"); */ initWithSpriteFrameName:function (spriteFrameName) { if(!spriteFrameName) throw "cc.Sprite.initWithSpriteFrameName(): spriteFrameName should be non-null"; var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(spriteFrameName); if(!frame) throw spriteFrameName + " is null, please check."; return this.initWithSpriteFrame(frame); }, /** * tell the sprite to use batch node render. * @param {cc.SpriteBatchNode} batchNode */ useBatchNode:function (batchNode) { this._textureAtlas = batchNode.getTextureAtlas(); // weak ref this._batchNode = batchNode; }, /** *

* set the vertex rect.
* It will be called internally by setTextureRect.
* Useful if you want to create 2x images from SD images in Retina Display.
* Do not call it manually. Use setTextureRect instead.
* (override this method to generate "double scale" sprites) *

* @param {cc.Rect} rect */ setVertexRect:function (rect) { this._rect.x = rect.x; this._rect.y = rect.y; this._rect.width = rect.width; this._rect.height = rect.height; }, sortAllChildren:function () { if (this._reorderChildDirty) { var j, tempItem, locChildren = this._children, tempChild; for (var i = 1; i < locChildren.length; i++) { tempItem = locChildren[i]; j = i - 1; tempChild = locChildren[j]; //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller while (j >= 0 && ( tempItem._zOrder < tempChild._zOrder || ( tempItem._zOrder == tempChild._zOrder && tempItem._orderOfArrival < tempChild._orderOfArrival ))) { locChildren[j + 1] = tempChild; j = j - 1; tempChild = locChildren[j]; } locChildren[j + 1] = tempItem; } if (this._batchNode) { this._arrayMakeObjectsPerformSelector(locChildren, cc.Node.StateCallbackType.sortAllChildren); } this._reorderChildDirty = false; } }, /** * Reorders a child according to a new z value. (override cc.Node ) * @param {cc.Node} child * @param {Number} zOrder * @override */ reorderChild:function (child, zOrder) { if(!child) throw "cc.Sprite.reorderChild(): child should be non-null"; if(this._children.indexOf(child) === -1){ cc.log("cc.Sprite.reorderChild(): this child is not in children list"); return; } if (zOrder === child.getZOrder()) return; if (this._batchNode && !this._reorderChildDirty) { this._setReorderChildDirtyRecursively(); this._batchNode.reorderBatch(true); } cc.Node.prototype.reorderChild.call(this, child, zOrder); }, /** * Removes a child from the sprite. (override cc.Node ) * @param child * @param cleanup whether or not cleanup all running actions * @override */ removeChild:function (child, cleanup) { if (this._batchNode) this._batchNode.removeSpriteFromAtlas(child); cc.Node.prototype.removeChild.call(this, child, cleanup); }, /** * Removes all children from the container (override cc.Node ) * @param cleanup whether or not cleanup all running actions * @override */ removeAllChildren:function (cleanup) { var locChildren = this._children, locBatchNode = this._batchNode; if (locBatchNode && locChildren != null) { for (var i = 0, len = locChildren.length; i < len; i++) locBatchNode.removeSpriteFromAtlas(locChildren[i]); } cc.Node.prototype.removeAllChildren.call(this, cleanup); this._hasChildren = false; }, // // cc.Node property overloads // /** * set Recursively is or isn't Dirty * used only when parent is cc.SpriteBatchNode * @param {Boolean} value */ setDirtyRecursively:function (value) { this._recursiveDirty = value; this.setDirty(value); // recursively set dirty var locChildren = this._children; if (locChildren != null) { for (var i = 0; i < locChildren.length; i++) { if (locChildren[i] instanceof cc.Sprite) locChildren[i].setDirtyRecursively(true); } } }, /** * HACK: optimization */ SET_DIRTY_RECURSIVELY:function () { if (this._batchNode && !this._recursiveDirty) { this._recursiveDirty = true; this._dirty = true; if (this._hasChildren) this.setDirtyRecursively(true); } }, /** * position setter (override cc.Node ) * @param {cc.Point|Number} pos position or x value of position * @param {Number} [yValue] y value of position * @override */ setPosition:function (pos, yValue) { if (arguments.length >= 2) cc.Node.prototype.setPosition.call(this, pos, arguments[1]); else cc.Node.prototype.setPosition.call(this, pos); this.SET_DIRTY_RECURSIVELY(); }, /** * Rotation setter (override cc.Node ) * @param {Number} rotation * @override */ setRotation:function (rotation) { cc.Node.prototype.setRotation.call(this, rotation); this.SET_DIRTY_RECURSIVELY(); }, setRotationX:function (rotationX) { cc.Node.prototype.setRotationX.call(this, rotationX); this.SET_DIRTY_RECURSIVELY(); }, setRotationY:function (rotationY) { cc.Node.prototype.setRotationY.call(this, rotationY); this.SET_DIRTY_RECURSIVELY(); }, /** * SkewX setter (override cc.Node ) * @param {Number} sx SkewX value * @override */ setSkewX:function (sx) { cc.Node.prototype.setSkewX.call(this, sx); this.SET_DIRTY_RECURSIVELY(); }, /** * SkewY setter (override cc.Node ) * @param {Number} sy SkewY value * @override */ setSkewY:function (sy) { cc.Node.prototype.setSkewY.call(this, sy); this.SET_DIRTY_RECURSIVELY(); }, /** * ScaleX setter (override cc.Node ) * @param {Number} scaleX * @override */ setScaleX:function (scaleX) { cc.Node.prototype.setScaleX.call(this, scaleX); this.SET_DIRTY_RECURSIVELY(); }, /** * ScaleY setter (override cc.Node ) * @param {Number} scaleY * @override */ setScaleY:function (scaleY) { cc.Node.prototype.setScaleY.call(this, scaleY); this.SET_DIRTY_RECURSIVELY(); }, /** *

The scale factor of the node. 1.0 is the default scale factor.
* It modifies the X and Y scale at the same time. (override cc.Node )

* @param {Number} scale * @param {Number|null} [scaleY=] * @override */ setScale:function (scale, scaleY) { cc.Node.prototype.setScale.call(this, scale, scaleY); this.SET_DIRTY_RECURSIVELY(); }, /** * VertexZ setter (override cc.Node ) * @param {Number} vertexZ * @override */ setVertexZ:function (vertexZ) { cc.Node.prototype.setVertexZ.call(this, vertexZ); this.SET_DIRTY_RECURSIVELY(); }, /** * Sets the anchor point in percent. (override cc.Node ) * @param {cc.Point|Number} anchor The anchor Sprite of Sprite or The anchor point.x of Sprite. * @param {Number} [y] The anchor point.y of Sprite. * @override */ setAnchorPoint:function (anchor, y) { cc.Node.prototype.setAnchorPoint.call(this, anchor, y); this.SET_DIRTY_RECURSIVELY(); }, /** * visible setter (override cc.Node ) * @param {Boolean} visible * @override */ setVisible:function (visible) { cc.Node.prototype.setVisible.call(this, visible); this.SET_DIRTY_RECURSIVELY(); }, /** * IsRelativeAnchorPoint setter (override cc.Node ) * @param {Boolean} relative * @override */ ignoreAnchorPointForPosition:function (relative) { if(this._batchNode){ cc.log("cc.Sprite.ignoreAnchorPointForPosition(): it is invalid in cc.Sprite when using SpriteBatchNode"); return; } cc.Node.prototype.ignoreAnchorPointForPosition.call(this, relative); }, /** * Sets whether the sprite should be flipped horizontally or not. * @param {Boolean} flippedX true if the sprite should be flipped horizontally, false otherwise. */ setFlippedX:function (flippedX) { if (this._flippedX != flippedX) { this._flippedX = flippedX; this.setTextureRect(this._rect, this._rectRotated, this._contentSize); this.setNodeDirty(); } }, /** * Sets whether the sprite should be flipped vertically or not. * @param {Boolean} flippedY true if the sprite should be flipped vertically, false otherwise. */ setFlippedY:function (flippedY) { if (this._flippedY != flippedY) { this._flippedY = flippedY; this.setTextureRect(this._rect, this._rectRotated, this._contentSize); this.setNodeDirty(); } }, /** *

* Returns the flag which indicates whether the sprite is flipped horizontally or not.
*
* It only flips the texture of the sprite, and not the texture of the sprite's children.
* Also, flipping the texture doesn't alter the anchorPoint.
* If you want to flip the anchorPoint too, and/or to flip the children too use:
* sprite->setScaleX(sprite->getScaleX() * -1);

* @return {Boolean} true if the sprite is flipped horizaontally, false otherwise. */ isFlippedX:function () { return this._flippedX; }, /** *

* Return the flag which indicates whether the sprite is flipped vertically or not.
*
* It only flips the texture of the sprite, and not the texture of the sprite's children.
* Also, flipping the texture doesn't alter the anchorPoint.
* If you want to flip the anchorPoint too, and/or to flip the children too use:
* sprite->setScaleY(sprite->getScaleY() * -1);

* @return {Boolean} true if the sprite is flipped vertically, flase otherwise. */ isFlippedY:function () { return this._flippedY; }, // // RGBA protocol // /** * opacity: conforms to CCRGBAProtocol protocol * @param {Boolean} modify */ setOpacityModifyRGB:null, _setOpacityModifyRGBForWebGL: function (modify) { if (this._opacityModifyRGB !== modify) { this._opacityModifyRGB = modify; this.updateColor(); } }, _setOpacityModifyRGBForCanvas: function (modify) { if (this._opacityModifyRGB !== modify) { this._opacityModifyRGB = modify; this.setNodeDirty(); } }, /** * return IsOpacityModifyRGB value * @return {Boolean} */ isOpacityModifyRGB:function () { return this._opacityModifyRGB; }, updateDisplayedOpacity: null, _updateDisplayedOpacityForWebGL:function (parentOpacity) { cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity); this.updateColor(); }, _updateDisplayedOpacityForCanvas:function (parentOpacity) { cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity); this._setNodeDirtyForCache(); }, // Animation /** * changes the display frame with animation name and index.
* The animation name will be get from the CCAnimationCache * @param animationName * @param frameIndex */ setDisplayFrameWithAnimationName:function (animationName, frameIndex) { if(!animationName) throw "cc.Sprite.setDisplayFrameWithAnimationName(): animationName must be non-null"; var cache = cc.AnimationCache.getInstance().getAnimation(animationName); if(!cache){ cc.log("cc.Sprite.setDisplayFrameWithAnimationName(): Frame not found"); return; } var animFrame = cache.getFrames()[frameIndex]; if(!animFrame){ cc.log("cc.Sprite.setDisplayFrameWithAnimationName(): Invalid frame index"); return; } this.setDisplayFrame(animFrame.getSpriteFrame()); }, /** * Returns the batch node object if this sprite is rendered by cc.SpriteBatchNode * @returns {cc.SpriteBatchNode|null} The cc.SpriteBatchNode object if this sprite is rendered by cc.SpriteBatchNode, null if the sprite isn't used batch node. */ getBatchNode:function () { return this._batchNode; }, _setReorderChildDirtyRecursively:function () { //only set parents flag the first time if (!this._reorderChildDirty) { this._reorderChildDirty = true; var pNode = this._parent; while (pNode && pNode != this._batchNode) { pNode._setReorderChildDirtyRecursively(); pNode = pNode.getParent(); } } }, // CCTextureProtocol getTexture:function () { return this._texture; }, _quad:null, // vertex coords, texture coords and color info _quadWebBuffer:null, _quadDirty:false, _colorized:false, _isLighterMode:false, _originalTexture:null, _textureRect_Canvas:null, _drawSize_Canvas:null, /** * Constructor * @param {String|cc.SpriteFrame|cc.SpriteBatchNode|HTMLImageElement|cc.Texture2D} fileName sprite construct parameter */ ctor: null, _ctorForWebGL: function (fileName) { cc.NodeRGBA.prototype.ctor.call(this); this._shouldBeHidden = false; this._offsetPosition = cc.p(0, 0); this._unflippedOffsetPositionFromCenter = cc.p(0, 0); this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST}; this._rect = cc.rect(0,0,0,0); this._quad = new cc.V3F_C4B_T2F_Quad(); this._quadWebBuffer = cc.renderContext.createBuffer(); this._quadDirty = true; this._textureLoaded = true; if (fileName) { if (typeof(fileName) === "string") { var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(fileName); this.initWithSpriteFrame(frame); } else if (typeof(fileName) === "object") { if (fileName instanceof cc.SpriteFrame) { this.initWithSpriteFrame(fileName); } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) { var texture2d = new cc.Texture2D(); texture2d.initWithElement(fileName); texture2d.handleLoadedTexture(); this.initWithTexture(texture2d); } else if (fileName instanceof cc.Texture2D) { this.initWithTexture(fileName); } } } }, _ctorForCanvas: function (fileName) { cc.NodeRGBA.prototype.ctor.call(this); this._shouldBeHidden = false; this._offsetPosition = cc.p(0, 0); this._unflippedOffsetPositionFromCenter = cc.p(0, 0); this._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST}; this._rect = cc.rect(0, 0, 0, 0); this._newTextureWhenChangeColor = false; this._textureLoaded = true; this._textureRect_Canvas = {x: 0, y: 0, width: 0, height:0, validRect: false}; this._drawSize_Canvas = cc.size(0, 0); if (fileName) { if (typeof(fileName) === "string") { var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(fileName); this.initWithSpriteFrame(frame); } else if (typeof(fileName) === "object") { if (fileName instanceof cc.SpriteFrame) { this.initWithSpriteFrame(fileName); } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) { var texture2d = new cc.Texture2D(); texture2d.initWithElement(fileName); texture2d.handleLoadedTexture(); this.initWithTexture(texture2d); } else if (fileName instanceof cc.Texture2D) { this.initWithTexture(fileName); } } } }, /** * Returns the quad (tex coords, vertex coords and color) information. * @return {cc.V3F_C4B_T2F_Quad} */ getQuad:function () { return this._quad; }, /** * conforms to cc.TextureProtocol protocol * @param {Number|cc.BlendFunc} src * @param {Number} dst */ setBlendFunc: null, _setBlendFuncForWebGL: function (src, dst) { var locBlendFunc = this._blendFunc; if (dst === undefined) { locBlendFunc.src = src.src; locBlendFunc.dst = src.dst; } else { locBlendFunc.src = src; locBlendFunc.dst = dst; } }, _setBlendFuncForCanvas: function (src, dst) { var locBlendFunc = this._blendFunc; if (dst === undefined) { locBlendFunc.src = src.src; locBlendFunc.dst = src.dst; } else { locBlendFunc.src = src; locBlendFunc.dst = dst; } this._isLighterMode = (locBlendFunc && (( locBlendFunc.src == gl.SRC_ALPHA && locBlendFunc.dst == gl.ONE) || (locBlendFunc.src == gl.ONE && locBlendFunc.dst == gl.ONE))); }, /** * Initializes an empty sprite with nothing init. * @return {Boolean} */ init:null, _initForWebGL: function () { if (arguments.length > 0) return this.initWithFile(arguments[0], arguments[1]); cc.NodeRGBA.prototype.init.call(this); this._dirty = this._recursiveDirty = false; this._opacityModifyRGB = true; this._blendFunc.src = cc.BLEND_SRC; this._blendFunc.dst = cc.BLEND_DST; // update texture (calls _updateBlendFunc) this.setTexture(null); this._textureLoaded = true; this._flippedX = this._flippedY = false; // default transform anchor: center this.setAnchorPoint(0.5, 0.5); // zwoptex default values this._offsetPosition.x = 0; this._offsetPosition.y = 0; this._hasChildren = false; // Atlas: Color var tempColor = {r: 255, g: 255, b: 255, a: 255}; this._quad.bl.colors = tempColor; this._quad.br.colors = tempColor; this._quad.tl.colors = tempColor; this._quad.tr.colors = tempColor; this._quadDirty = true; // updated in "useSelfRender" // Atlas: TexCoords this.setTextureRect(cc.RectZero(), false, cc.SizeZero()); return true; }, _initForCanvas: function () { if (arguments.length > 0) return this.initWithFile(arguments[0], arguments[1]); cc.NodeRGBA.prototype.init.call(this); this._dirty = this._recursiveDirty = false; this._opacityModifyRGB = true; this._blendFunc.src = cc.BLEND_SRC; this._blendFunc.dst = cc.BLEND_DST; // update texture (calls _updateBlendFunc) this.setTexture(null); this._textureLoaded = true; this._flippedX = this._flippedY = false; // default transform anchor: center this.setAnchorPoint(0.5, 0.5); // zwoptex default values this._offsetPosition.x = 0; this._offsetPosition.y = 0; this._hasChildren = false; // updated in "useSelfRender" // Atlas: TexCoords this.setTextureRect(cc.RectZero(), false, cc.SizeZero()); return true; }, /** *

* Initializes a sprite with an image filename. * * This method will find pszFilename from local file system, load its content to CCTexture2D, * then use CCTexture2D to create a sprite. * After initialization, the rect used will be the size of the image. The offset will be (0,0). *

* @param {String} filename The path to an image file in local file system * @param {cc.Rect} rect The rectangle assigned the content area from texture. * @return {Boolean} true if the sprite is initialized properly, false otherwise. * @example * var mySprite = new cc.Sprite(); * mySprite.initWithFile("HelloHTML5World.png",cc.rect(0,0,480,320)); */ initWithFile:function (filename, rect) { if(!filename) throw "cc.Sprite.initWithFile(): filename should be non-null"; var texture = cc.TextureCache.getInstance().textureForKey(filename); if (!texture) { texture = cc.TextureCache.getInstance().addImage(filename); return this.initWithTexture(texture, rect); } else { if (!rect) { var size = texture.getContentSize(); rect = cc.rect(0, 0, size.width, size.height); } return this.initWithTexture(texture, rect); } }, /** * Initializes a sprite with a texture and a rect in points, optionally rotated.
* After initialization, the rect used will be the size of the texture, and the offset will be (0,0). * @param {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} texture A pointer to an existing CCTexture2D object. You can use a CCTexture2D object for many sprites. * @param {cc.Rect} rect Only the contents inside rect of this texture will be applied for this sprite. * @param {Boolean} [rotated] Whether or not the texture rectangle is rotated. * @return {Boolean} true if the sprite is initialized properly, false otherwise. * @example * var img =cc.TextureCache.getInstance().addImage("HelloHTML5World.png"); * var mySprite = new cc.Sprite(); * mySprite.initWithTexture(img,cc.rect(0,0,480,320)); */ initWithTexture: null, _initWithTextureForWebGL: function (texture, rect, rotated) { var argnum = arguments.length; if (argnum == 0) throw "Sprite.initWithTexture(): Argument must be non-nil "; rotated = rotated || false; if (!cc.NodeRGBA.prototype.init.call(this)) return false; this._batchNode = null; this._recursiveDirty = false; this._dirty = false; this._opacityModifyRGB = true; this._blendFunc.src = cc.BLEND_SRC; this._blendFunc.dst = cc.BLEND_DST; this._flippedX = this._flippedY = false; // default transform anchor: center this.setAnchorPoint(0.5, 0.5); // zwoptex default values this._offsetPosition.x = 0; this._offsetPosition.y = 0; this._hasChildren = false; // Atlas: Color var tmpColor = new cc.Color4B(255, 255, 255, 255); var locQuad = this._quad; locQuad.bl.colors = tmpColor; locQuad.br.colors = tmpColor; locQuad.tl.colors = tmpColor; locQuad.tr.colors = tmpColor; var locTextureLoaded = texture.isLoaded(); this._textureLoaded = locTextureLoaded; if (!locTextureLoaded) { this._rectRotated = rotated || false; if (rect) { var locRect = this._rect; locRect.x = rect.x; locRect.y = rect.y; locRect.width = rect.width; locRect.height = rect.height; } texture.addLoadedEventListener(this._textureLoadedCallback, this); return true; } if (!rect) { var locSize1 = texture.getContentSize(); rect = cc.rect(0, 0, locSize1.width, locSize1.height); } this.setTexture(texture); this.setTextureRect(rect, rotated, rect._size); // by default use "Self Render". // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" this.setBatchNode(null); this._quadDirty = true; return true; }, _initWithTextureForCanvas: function (texture, rect, rotated) { var argnum = arguments.length; if (argnum == 0) throw "Sprite.initWithTexture(): Argument must be non-nil "; rotated = rotated || false; if (!cc.NodeRGBA.prototype.init.call(this)) return false; this._batchNode = null; this._recursiveDirty = false; this._dirty = false; this._opacityModifyRGB = true; this._blendFunc.src = cc.BLEND_SRC; this._blendFunc.dst = cc.BLEND_DST; this._flippedX = this._flippedY = false; // default transform anchor: center this.setAnchorPoint(0.5, 0.5); // zwoptex default values this._offsetPosition.x = 0; this._offsetPosition.y = 0; this._hasChildren = false; var locTextureLoaded = texture.isLoaded(); this._textureLoaded = locTextureLoaded; if (!locTextureLoaded) { this._rectRotated = rotated || false; if (rect) { this._rect.x = rect.x; this._rect.y = rect.y; this._rect.width = rect.width; this._rect.height = rect.height; } texture.addLoadedEventListener(this._textureLoadedCallback, this); return true; } if (!rect) { var locSize1 = texture.getContentSize(); rect = cc.rect(0, 0, locSize1.width, locSize1.height); } this._originalTexture = texture; this.setTexture(texture); this.setTextureRect(rect, rotated, rect._size); // by default use "Self Render". // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" this.setBatchNode(null); return true; }, _textureLoadedCallback: null, _textureLoadedCallbackForWebGL: function (sender) { if(this._textureLoaded) return; this._textureLoaded = true; var locRect = this._rect; if (!locRect) { var locSize1 = sender.getContentSize(); locRect = cc.rect(0, 0, locSize1.width, locSize1.height); } else if (cc._rectEqualToZero(locRect)) { var locSize2 = sender.getContentSize(); locRect.width = locSize2.width; locRect.height = locSize2.height; } this.setTexture(sender); this.setTextureRect(locRect, this._rectRotated, locRect._size); // by default use "Self Render". // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" this.setBatchNode(this._batchNode); this._quadDirty = true; this._callLoadedEventCallbacks(); }, _textureLoadedCallbackForCanvas: function (sender) { if(this._textureLoaded) return; this._textureLoaded = true; var locRect = this._rect; if (!locRect) { var locSize1 = sender.getContentSize(); locRect = cc.rect(0, 0, locSize1.width, locSize1.height); } else if (cc._rectEqualToZero(locRect)) { var locSize2 = sender.getContentSize(); locRect.width = locSize2.width; locRect.height = locSize2.height; } this._originalTexture = sender; this.setTexture(sender); this.setTextureRect(locRect, this._rectRotated, locRect._size); // by default use "Self Render". // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" this.setBatchNode(this._batchNode); this._callLoadedEventCallbacks(); }, /** * updates the texture rect of the CCSprite in points. * @param {cc.Rect} rect a rect of texture * @param {Boolean} rotated * @param {cc.Size} untrimmedSize */ setTextureRect:null, _setTextureRectForWebGL:function (rect, rotated, untrimmedSize) { this._rectRotated = rotated || false; untrimmedSize = untrimmedSize || rect._size; this.setContentSize(untrimmedSize); this.setVertexRect(rect); this._setTextureCoords(rect); var relativeOffset = this._unflippedOffsetPositionFromCenter; if (this._flippedX) relativeOffset.x = -relativeOffset.x; if (this._flippedY) relativeOffset.y = -relativeOffset.y; var locRect = this._rect; this._offsetPosition.x = relativeOffset.x + (this._contentSize.width - locRect.width) / 2; this._offsetPosition.y = relativeOffset.y + (this._contentSize.height - locRect.height) / 2; // rendering using batch node if (this._batchNode) { // update dirty_, don't update recursiveDirty_ //this.setDirty(true); this._dirty = true; } else { // self rendering // Atlas: Vertex var x1 = 0 + this._offsetPosition.x; var y1 = 0 + this._offsetPosition.y; var x2 = x1 + locRect.width; var y2 = y1 + locRect.height; // Don't update Z. var locQuad = this._quad; locQuad.bl.vertices = {x:x1, y:y1, z:0}; locQuad.br.vertices = {x:x2, y:y1, z:0}; locQuad.tl.vertices = {x:x1, y:y2, z:0}; locQuad.tr.vertices = {x:x2, y:y2, z:0}; this._quadDirty = true; } }, _setTextureRectForCanvas: function (rect, rotated, untrimmedSize) { this._rectRotated = rotated || false; untrimmedSize = untrimmedSize || rect._size; this.setContentSize(untrimmedSize); this.setVertexRect(rect); var locTextureRect = this._textureRect_Canvas, scaleFactor = cc.CONTENT_SCALE_FACTOR(); locTextureRect.x = 0 | (rect.x * scaleFactor); locTextureRect.y = 0 | (rect.y * scaleFactor); locTextureRect.width = 0 | (rect.width * scaleFactor); locTextureRect.height = 0 | (rect.height * scaleFactor); locTextureRect.validRect = !(locTextureRect.width === 0 || locTextureRect.height === 0 || locTextureRect.x < 0 || locTextureRect.y < 0); var relativeOffset = this._unflippedOffsetPositionFromCenter; if (this._flippedX) relativeOffset.x = -relativeOffset.x; if (this._flippedY) relativeOffset.y = -relativeOffset.y; this._offsetPosition.x = relativeOffset.x + (this._contentSize.width - this._rect.width) / 2; this._offsetPosition.y = relativeOffset.y + (this._contentSize.height - this._rect.height) / 2; // rendering using batch node if (this._batchNode) { // update dirty_, don't update recursiveDirty_ //this.setDirty(true); this._dirty = true; } }, // BatchNode methods /** * updates the quad according the the rotation, position, scale values. */ updateTransform: null, _updateTransformForWebGL: function () { //cc.Assert(this._batchNode, "updateTransform is only valid when cc.Sprite is being rendered using an cc.SpriteBatchNode"); // recaculate matrix only if it is dirty if (this.isDirty()) { var locQuad = this._quad, locParent = this._parent; // If it is not visible, or one of its ancestors is not visible, then do nothing: if (!this._visible || ( locParent && locParent != this._batchNode && locParent._shouldBeHidden)) { locQuad.br.vertices = {x: 0, y: 0, z: 0}; locQuad.tl.vertices = {x: 0, y: 0, z: 0}; locQuad.tr.vertices = {x: 0, y: 0, z: 0}; locQuad.bl.vertices = {x: 0, y: 0, z: 0}; this._shouldBeHidden = true; } else { this._shouldBeHidden = false; if (!locParent || locParent == this._batchNode) { this._transformToBatch = this.nodeToParentTransform(); } else { //cc.Assert(this._parent instanceof cc.Sprite, "Logic error in CCSprite. Parent must be a CCSprite"); this._transformToBatch = cc.AffineTransformConcat(this.nodeToParentTransform(), locParent._transformToBatch); } // // calculate the Quad based on the Affine Matrix // var locTransformToBatch = this._transformToBatch; var size = this._rect._size; var x1 = this._offsetPosition.x; var y1 = this._offsetPosition.y; var x2 = x1 + size.width; var y2 = y1 + size.height; var x = locTransformToBatch.tx; var y = locTransformToBatch.ty; var cr = locTransformToBatch.a; var sr = locTransformToBatch.b; var cr2 = locTransformToBatch.d; var sr2 = -locTransformToBatch.c; var ax = x1 * cr - y1 * sr2 + x; var ay = x1 * sr + y1 * cr2 + y; var bx = x2 * cr - y1 * sr2 + x; var by = x2 * sr + y1 * cr2 + y; var cx = x2 * cr - y2 * sr2 + x; var cy = x2 * sr + y2 * cr2 + y; var dx = x1 * cr - y2 * sr2 + x; var dy = x1 * sr + y2 * cr2 + y; var locVertexZ = this._vertexZ; locQuad.bl.vertices = {x: cc.RENDER_IN_SUBPIXEL(ax), y: cc.RENDER_IN_SUBPIXEL(ay), z: locVertexZ}; locQuad.br.vertices = {x: cc.RENDER_IN_SUBPIXEL(bx), y: cc.RENDER_IN_SUBPIXEL(by), z: locVertexZ}; locQuad.tl.vertices = {x: cc.RENDER_IN_SUBPIXEL(dx), y: cc.RENDER_IN_SUBPIXEL(dy), z: locVertexZ}; locQuad.tr.vertices = {x: cc.RENDER_IN_SUBPIXEL(cx), y: cc.RENDER_IN_SUBPIXEL(cy), z: locVertexZ}; } this._textureAtlas.updateQuad(locQuad, this._atlasIndex); this._recursiveDirty = false; this.setDirty(false); } // recursively iterate over children if (this._hasChildren) this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform); if (cc.SPRITE_DEBUG_DRAW) { // draw bounding box var vertices = [ cc.p(this._quad.bl.vertices.x, this._quad.bl.vertices.y), cc.p(this._quad.br.vertices.x, this._quad.br.vertices.y), cc.p(this._quad.tr.vertices.x, this._quad.tr.vertices.y), cc.p(this._quad.tl.vertices.x, this._quad.tl.vertices.y) ]; cc.drawingUtil.drawPoly(vertices, 4, true); } }, _updateTransformForCanvas: function () { //cc.Assert(this._batchNode, "updateTransform is only valid when cc.Sprite is being rendered using an cc.SpriteBatchNode"); // recaculate matrix only if it is dirty if (this._dirty) { // If it is not visible, or one of its ancestors is not visible, then do nothing: var locParent = this._parent; if (!this._visible || ( locParent && locParent != this._batchNode && locParent._shouldBeHidden)) { this._shouldBeHidden = true; } else { this._shouldBeHidden = false; if (!locParent || locParent == this._batchNode) { this._transformToBatch = this.nodeToParentTransform(); } else { //cc.Assert(this._parent instanceof cc.Sprite, "Logic error in CCSprite. Parent must be a CCSprite"); this._transformToBatch = cc.AffineTransformConcat(this.nodeToParentTransform(), locParent._transformToBatch); } } this._recursiveDirty = false; this._dirty = false; } // recursively iterate over children if (this._hasChildren) this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform); }, /** * Add child to sprite (override cc.Node ) * @param {cc.Sprite} child * @param {Number} zOrder child's zOrder * @param {String} tag child's tag * @override */ addChild: null, _addChildForWebGL:function (child, zOrder, tag) { if(!child) throw "cc.Sprite.addChild(): child should be non-null"; if (zOrder == null) zOrder = child._zOrder; if (tag == null) tag = child._tag; if (this._batchNode) { if(!(child instanceof cc.Sprite)){ cc.log("cc.Sprite.addChild(): cc.Sprite only supports cc.Sprites as children when using cc.SpriteBatchNode"); return; } if(child.getTexture()._webTextureObj !== this._textureAtlas.getTexture()._webTextureObj) cc.log("cc.Sprite.addChild(): cc.Sprite only supports a sprite using same texture as children when using cc.SpriteBatchNode"); //put it in descendants array of batch node this._batchNode.appendChild(child); if (!this._reorderChildDirty) this._setReorderChildDirtyRecursively(); } //cc.Node already sets isReorderChildDirty_ so this needs to be after batchNode check cc.NodeRGBA.prototype.addChild.call(this, child, zOrder, tag); this._hasChildren = true; }, _addChildForCanvas: function (child, zOrder, tag) { if(!child) throw "cc.Sprite.addChild(): child should be non-null"; if (zOrder == null) zOrder = child._zOrder; if (tag == null) tag = child._tag; //cc.Node already sets isReorderChildDirty_ so this needs to be after batchNode check cc.NodeRGBA.prototype.addChild.call(this, child, zOrder, tag); this._hasChildren = true; }, /** * Update sprite's color */ updateColor:function () { var locDisplayedColor = this._displayedColor, locDisplayedOpacity = this._displayedOpacity; var color4 = {r: locDisplayedColor.r, g: locDisplayedColor.g, b: locDisplayedColor.b, a: locDisplayedOpacity}; // special opacity for premultiplied textures if (this._opacityModifyRGB) { color4.r *= locDisplayedOpacity / 255.0; color4.g *= locDisplayedOpacity / 255.0; color4.b *= locDisplayedOpacity / 255.0; } var locQuad = this._quad; locQuad.bl.colors = color4; locQuad.br.colors = color4; locQuad.tl.colors = color4; locQuad.tr.colors = color4; // renders using Sprite Manager if (this._batchNode) { if (this._atlasIndex != cc.SPRITE_INDEX_NOT_INITIALIZED) { this._textureAtlas.updateQuad(locQuad, this._atlasIndex) } else { // no need to set it recursively // update dirty_, don't update recursiveDirty_ //this.setDirty(true); this._dirty = true; } } // self render // do nothing this._quadDirty = true; }, /** * opacity setter * @param {Number} opacity */ setOpacity:null, _setOpacityForWebGL: function (opacity) { cc.NodeRGBA.prototype.setOpacity.call(this, opacity); this.updateColor(); }, _setOpacityForCanvas: function (opacity) { cc.NodeRGBA.prototype.setOpacity.call(this, opacity); this._setNodeDirtyForCache(); }, /** * color setter * @param {cc.Color3B} color3 */ setColor: null, _setColorForWebGL: function (color3) { cc.NodeRGBA.prototype.setColor.call(this, color3); this.updateColor(); }, _setColorForCanvas: function (color3) { var curColor = this.getColor(); if ((curColor.r === color3.r) && (curColor.g === color3.g) && (curColor.b === color3.b)) return; cc.NodeRGBA.prototype.setColor.call(this, color3); this._changeTextureColor(); this._setNodeDirtyForCache(); }, updateDisplayedColor: null, _updateDisplayedColorForWebGL: function (parentColor) { cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor); this.updateColor(); }, _updateDisplayedColorForCanvas: function (parentColor) { var oldColor = this.getColor(); cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor); var newColor = this._displayedColor; if ((oldColor.r === newColor.r) && (oldColor.g === newColor.g) && (oldColor.b === newColor.b)) return; this._changeTextureColor(); this._setNodeDirtyForCache(); }, // Frames /** * Sets a new display frame to the cc.Sprite. * @param {cc.SpriteFrame} newFrame */ setDisplayFrame: null, _setDisplayFrameForWebGL: function (newFrame) { this.setNodeDirty(); var frameOffset = newFrame.getOffset(); this._unflippedOffsetPositionFromCenter.x = frameOffset.x; this._unflippedOffsetPositionFromCenter.y = frameOffset.y; var pNewTexture = newFrame.getTexture(); var locTextureLoaded = newFrame.textureLoaded(); if (!locTextureLoaded) { this._textureLoaded = false; newFrame.addLoadedEventListener(function (sender) { this._textureLoaded = true; var locNewTexture = sender.getTexture(); if (locNewTexture != this._texture) this.setTexture(locNewTexture); this.setTextureRect(sender.getRect(), sender.isRotated(), sender.getOriginalSize()); this._callLoadedEventCallbacks(); }, this); } // update texture before updating texture rect if (pNewTexture != this._texture) this.setTexture(pNewTexture); // update rect this._rectRotated = newFrame.isRotated(); this.setTextureRect(newFrame.getRect(), this._rectRotated, newFrame.getOriginalSize()); }, _setDisplayFrameForCanvas: function (newFrame) { this.setNodeDirty(); var frameOffset = newFrame.getOffset(); this._unflippedOffsetPositionFromCenter.x = frameOffset.x; this._unflippedOffsetPositionFromCenter.y = frameOffset.y; // update rect this._rectRotated = newFrame.isRotated(); var pNewTexture = newFrame.getTexture(); var locTextureLoaded = newFrame.textureLoaded(); if (!locTextureLoaded) { this._textureLoaded = false; newFrame.addLoadedEventListener(function (sender) { this._textureLoaded = true; var locNewTexture = sender.getTexture(); if (locNewTexture != this._texture) this.setTexture(locNewTexture); this.setTextureRect(sender.getRect(), sender.isRotated(), sender.getOriginalSize()); this._callLoadedEventCallbacks(); }, this); } // update texture before updating texture rect if (pNewTexture != this._texture) this.setTexture(pNewTexture); if (this._rectRotated) this._originalTexture = pNewTexture; this.setTextureRect(newFrame.getRect(), this._rectRotated, newFrame.getOriginalSize()); this._colorized = false; if (locTextureLoaded) { var curColor = this.getColor(); if (curColor.r !== 255 || curColor.g !== 255 || curColor.b !== 255) this._changeTextureColor(); } }, /** * Returns whether or not a cc.SpriteFrame is being displayed * @param {cc.SpriteFrame} frame * @return {Boolean} */ isFrameDisplayed: null, _isFrameDisplayedForWebGL: function (frame) { return (cc.rectEqualToRect(frame.getRect(), this._rect) && frame.getTexture().getName() == this._texture.getName() && cc.pointEqualToPoint(frame.getOffset(), this._unflippedOffsetPositionFromCenter)); }, _isFrameDisplayedForCanvas: function (frame) { if (frame.getTexture() != this._texture) return false; return cc.rectEqualToRect(frame.getRect(), this._rect); }, /** * Returns the current displayed frame. * @return {cc.SpriteFrame} */ displayFrame: function () { return cc.SpriteFrame.createWithTexture(this._texture, cc.RECT_POINTS_TO_PIXELS(this._rect), this._rectRotated, cc.POINT_POINTS_TO_PIXELS(this._unflippedOffsetPositionFromCenter), cc.SIZE_POINTS_TO_PIXELS(this._contentSize)); }, /** * Sets the batch node to sprite * @param {cc.SpriteBatchNode|null} spriteBatchNode * @example * var batch = cc.SpriteBatchNode.create("Images/grossini_dance_atlas.png", 15); * var sprite = cc.Sprite.createWithTexture(batch.getTexture(), cc.rect(0, 0, 57, 57)); * batch.addChild(sprite); * layer.addChild(batch); */ setBatchNode:null, _setBatchNodeForWebGL:function (spriteBatchNode) { this._batchNode = spriteBatchNode; // weak reference // self render if (!this._batchNode) { this._atlasIndex = cc.SPRITE_INDEX_NOT_INITIALIZED; this.setTextureAtlas(null); this._recursiveDirty = false; this.setDirty(false); var x1 = this._offsetPosition.x; var y1 = this._offsetPosition.y; var x2 = x1 + this._rect.width; var y2 = y1 + this._rect.height; var locQuad = this._quad; locQuad.bl.vertices = {x:x1, y:y1, z:0}; locQuad.br.vertices = {x:x2, y:y1, z:0}; locQuad.tl.vertices = {x:x1, y:y2, z:0}; locQuad.tr.vertices = {x:x2, y:y2, z:0}; this._quadDirty = true; } else { // using batch this._transformToBatch = cc.AffineTransformIdentity(); this.setTextureAtlas(this._batchNode.getTextureAtlas()); // weak ref } }, _setBatchNodeForCanvas:function (spriteBatchNode) { this._batchNode = spriteBatchNode; // weak reference // self render if (!this._batchNode) { this._atlasIndex = cc.SPRITE_INDEX_NOT_INITIALIZED; this.setTextureAtlas(null); this._recursiveDirty = false; this.setDirty(false); } else { // using batch this._transformToBatch = cc.AffineTransformIdentity(); this.setTextureAtlas(this._batchNode.getTextureAtlas()); // weak ref } }, // CCTextureProtocol /** * Texture of sprite setter * @param {cc.Texture2D} texture */ setTexture: null, _setTextureForWebGL: function (texture) { // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet if(texture && !(texture instanceof cc.Texture2D)) throw "cc.Sprite.setTexture(): setTexture expects a CCTexture2D. Invalid argument"; // If batchnode, then texture id should be the same if(this._batchNode && this._batchNode.getTexture() != texture) { cc.log("cc.Sprite.setTexture(): Batched sprites should use the same texture as the batchnode"); return; } if (texture) this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR)); else this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_COLOR)); if (!this._batchNode && this._texture != texture) { this._texture = texture; this._updateBlendFunc(); } }, _setTextureForCanvas: function (texture) { // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet if(texture && !(texture instanceof cc.Texture2D)) throw "cc.Sprite.setTexture(): setTexture expects a CCTexture2D. Invalid argument"; if (this._texture != texture) { if (texture && texture.getHtmlElementObj() instanceof HTMLImageElement) { this._originalTexture = texture; } this._texture = texture; } }, // Texture protocol _updateBlendFunc:function () { if(this._batchNode){ cc.log("cc.Sprite._updateBlendFunc(): _updateBlendFunc doesn't work when the sprite is rendered using a cc.CCSpriteBatchNode"); return; } // it's possible to have an untextured sprite if (!this._texture || !this._texture.hasPremultipliedAlpha()) { this._blendFunc.src = gl.SRC_ALPHA; this._blendFunc.dst = gl.ONE_MINUS_SRC_ALPHA; this.setOpacityModifyRGB(false); } else { this._blendFunc.src = cc.BLEND_SRC; this._blendFunc.dst = cc.BLEND_DST; this.setOpacityModifyRGB(true); } }, _changeTextureColor: function () { var locElement, locTexture = this._texture, locRect = this._textureRect_Canvas; //this.getTextureRect(); if (locTexture && locRect.validRect && this._originalTexture) { locElement = locTexture.getHtmlElementObj(); if (!locElement) return; var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(this._originalTexture.getHtmlElementObj()); if (cacheTextureForColor) { this._colorized = true; //generate color texture cache if (locElement instanceof HTMLCanvasElement && !this._rectRotated && !this._newTextureWhenChangeColor) cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, locRect, locElement); else { locElement = cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, locRect); locTexture = new cc.Texture2D(); locTexture.initWithElement(locElement); locTexture.handleLoadedTexture(); this.setTexture(locTexture); } } } }, _setTextureCoords:function (rect) { rect = cc.RECT_POINTS_TO_PIXELS(rect); var tex = this._batchNode ? this._textureAtlas.getTexture() : this._texture; if (!tex) return; var atlasWidth = tex.getPixelsWide(); var atlasHeight = tex.getPixelsHigh(); var left, right, top, bottom, tempSwap, locQuad = this._quad; if (this._rectRotated) { if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) { left = (2 * rect.x + 1) / (2 * atlasWidth); right = left + (rect.height * 2 - 2) / (2 * atlasWidth); top = (2 * rect.y + 1) / (2 * atlasHeight); bottom = top + (rect.width * 2 - 2) / (2 * atlasHeight); } else { left = rect.x / atlasWidth; right = (rect.x + rect.height) / atlasWidth; top = rect.y / atlasHeight; bottom = (rect.y + rect.width) / atlasHeight; }// CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL if (this._flippedX) { tempSwap = top; top = bottom; bottom = tempSwap; } if (this._flippedY) { tempSwap = left; left = right; right = tempSwap; } locQuad.bl.texCoords.u = left; locQuad.bl.texCoords.v = top; locQuad.br.texCoords.u = left; locQuad.br.texCoords.v = bottom; locQuad.tl.texCoords.u = right; locQuad.tl.texCoords.v = top; locQuad.tr.texCoords.u = right; locQuad.tr.texCoords.v = bottom; } else { if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) { left = (2 * rect.x + 1) / (2 * atlasWidth); right = left + (rect.width * 2 - 2) / (2 * atlasWidth); top = (2 * rect.y + 1) / (2 * atlasHeight); bottom = top + (rect.height * 2 - 2) / (2 * atlasHeight); } else { left = rect.x / atlasWidth; right = (rect.x + rect.width) / atlasWidth; top = rect.y / atlasHeight; bottom = (rect.y + rect.height) / atlasHeight; } // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL if (this._flippedX) { tempSwap = left; left = right; right = tempSwap; } if (this._flippedY) { tempSwap = top; top = bottom; bottom = tempSwap; } locQuad.bl.texCoords.u = left; locQuad.bl.texCoords.v = bottom; locQuad.br.texCoords.u = right; locQuad.br.texCoords.v = bottom; locQuad.tl.texCoords.u = left; locQuad.tl.texCoords.v = top; locQuad.tr.texCoords.u = right; locQuad.tr.texCoords.v = top; } this._quadDirty = true; }, /** * draw sprite to canvas */ draw: null, _drawForWebGL: function () { if (!this._textureLoaded) return; var gl = cc.renderContext, locTexture = this._texture; //cc.Assert(!this._batchNode, "If cc.Sprite is being rendered by cc.SpriteBatchNode, cc.Sprite#draw SHOULD NOT be called"); if (locTexture) { if (locTexture._isLoaded) { this._shaderProgram.use(); this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4(); cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst); //optimize performance for javascript cc.glBindTexture2DN(0, locTexture); // = cc.glBindTexture2D(locTexture); cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POS_COLOR_TEX); gl.bindBuffer(gl.ARRAY_BUFFER, this._quadWebBuffer); if (this._quadDirty) { gl.bufferData(gl.ARRAY_BUFFER, this._quad.arrayBuffer, gl.DYNAMIC_DRAW); this._quadDirty = false; } gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 24, 0); //cc.VERTEX_ATTRIB_POSITION gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 24, 12); //cc.VERTEX_ATTRIB_COLOR gl.vertexAttribPointer(2, 2, gl.FLOAT, false, 24, 16); //cc.VERTEX_ATTRIB_TEX_COORDS gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); } } else { this._shaderProgram.use(); this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4(); cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst); cc.glBindTexture2D(null); cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR); gl.bindBuffer(gl.ARRAY_BUFFER, this._quadWebBuffer); if (this._quadDirty) { cc.renderContext.bufferData(cc.renderContext.ARRAY_BUFFER, this._quad.arrayBuffer, cc.renderContext.STATIC_DRAW); this._quadDirty = false; } gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0); gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); } cc.g_NumberOfDraws++; if (cc.SPRITE_DEBUG_DRAW === 0) return; if (cc.SPRITE_DEBUG_DRAW === 1) { // draw bounding box var locQuad = this._quad; var verticesG1 = [ cc.p(locQuad.tl.vertices.x, locQuad.tl.vertices.y), cc.p(locQuad.bl.vertices.x, locQuad.bl.vertices.y), cc.p(locQuad.br.vertices.x, locQuad.br.vertices.y), cc.p(locQuad.tr.vertices.x, locQuad.tr.vertices.y) ]; cc.drawingUtil.drawPoly(verticesG1, 4, true); } else if (cc.SPRITE_DEBUG_DRAW === 2) { // draw texture box var drawSizeG2 = this.getTextureRect()._size; var offsetPixG2 = this.getOffsetPosition(); var verticesG2 = [cc.p(offsetPixG2.x, offsetPixG2.y), cc.p(offsetPixG2.x + drawSizeG2.width, offsetPixG2.y), cc.p(offsetPixG2.x + drawSizeG2.width, offsetPixG2.y + drawSizeG2.height), cc.p(offsetPixG2.x, offsetPixG2.y + drawSizeG2.height)]; cc.drawingUtil.drawPoly(verticesG2, 4, true); } // CC_SPRITE_DEBUG_DRAW }, _drawForCanvas: function (ctx) { if (!this._textureLoaded) return; var context = ctx || cc.renderContext; if (this._isLighterMode) context.globalCompositeOperation = 'lighter'; var locEGL_ScaleX = cc.EGLView.getInstance().getScaleX(), locEGL_ScaleY = cc.EGLView.getInstance().getScaleY(); context.globalAlpha = this._displayedOpacity / 255; var locRect = this._rect, locContentSize = this._contentSize, locOffsetPosition = this._offsetPosition, locDrawSizeCanvas = this._drawSize_Canvas; var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height, locTextureCoord = this._textureRect_Canvas; locDrawSizeCanvas.width = locRect.width * locEGL_ScaleX; locDrawSizeCanvas.height = locRect.height * locEGL_ScaleY; if (this._flippedX || this._flippedY) { context.save(); if (this._flippedX) { flipXOffset = -locOffsetPosition.x - locRect.width; context.scale(-1, 1); } if (this._flippedY) { flipYOffset = locOffsetPosition.y; context.scale(1, -1); } } flipXOffset *= locEGL_ScaleX; flipYOffset *= locEGL_ScaleY; if (this._texture && locTextureCoord.validRect) { var image = this._texture.getHtmlElementObj(); if (this._colorized) { context.drawImage(image, 0, 0, locTextureCoord.width, locTextureCoord.height, flipXOffset, flipYOffset, locDrawSizeCanvas.width, locDrawSizeCanvas.height); } else { context.drawImage(image, locTextureCoord.x, locTextureCoord.y, locTextureCoord.width, locTextureCoord.height, flipXOffset, flipYOffset, locDrawSizeCanvas.width , locDrawSizeCanvas.height); } } else if (locContentSize.width !== 0) { var curColor = this.getColor(); context.fillStyle = "rgba(" + curColor.r + "," + curColor.g + "," + curColor.b + ",1)"; context.fillRect(flipXOffset, flipYOffset, locContentSize.width * locEGL_ScaleX, locContentSize.height * locEGL_ScaleY); } if (cc.SPRITE_DEBUG_DRAW === 1) { // draw bounding box context.strokeStyle = "rgba(0,255,0,1)"; flipXOffset /= locEGL_ScaleX; flipYOffset /= locEGL_ScaleY; flipYOffset = -flipYOffset; var vertices1 = [cc.p(flipXOffset, flipYOffset), cc.p(flipXOffset + locRect.width, flipYOffset), cc.p(flipXOffset + locRect.width, flipYOffset - locRect.height), cc.p(flipXOffset, flipYOffset - locRect.height)]; cc.drawingUtil.drawPoly(vertices1, 4, true); } else if (cc.SPRITE_DEBUG_DRAW === 2) { // draw texture box context.strokeStyle = "rgba(0,255,0,1)"; var drawSize = this._rect._size; flipYOffset = -flipYOffset; var vertices2 = [cc.p(flipXOffset, flipYOffset), cc.p(flipXOffset + drawSize.width, flipYOffset), cc.p(flipXOffset + drawSize.width, flipYOffset - drawSize.height), cc.p(flipXOffset, flipYOffset - drawSize.height)]; cc.drawingUtil.drawPoly(vertices2, 4, true); } if (this._flippedX || this._flippedY) context.restore(); cc.g_NumberOfDraws++; } }); if(cc.Browser.supportWebGL){ cc.Sprite.prototype._spriteFrameLoadedCallback = cc.Sprite.prototype._spriteFrameLoadedCallbackForWebGL; cc.Sprite.prototype.setOpacityModifyRGB = cc.Sprite.prototype._setOpacityModifyRGBForWebGL; cc.Sprite.prototype.updateDisplayedOpacity = cc.Sprite.prototype._updateDisplayedOpacityForWebGL; cc.Sprite.prototype.ctor = cc.Sprite.prototype._ctorForWebGL; cc.Sprite.prototype.setBlendFunc = cc.Sprite.prototype._setBlendFuncForWebGL; cc.Sprite.prototype.init = cc.Sprite.prototype._initForWebGL; cc.Sprite.prototype.initWithTexture = cc.Sprite.prototype._initWithTextureForWebGL; cc.Sprite.prototype._textureLoadedCallback = cc.Sprite.prototype._textureLoadedCallbackForWebGL; cc.Sprite.prototype.setTextureRect = cc.Sprite.prototype._setTextureRectForWebGL; cc.Sprite.prototype.updateTransform = cc.Sprite.prototype._updateTransformForWebGL; cc.Sprite.prototype.addChild = cc.Sprite.prototype._addChildForWebGL; cc.Sprite.prototype.setOpacity = cc.Sprite.prototype._setOpacityForWebGL; cc.Sprite.prototype.setColor = cc.Sprite.prototype._setColorForWebGL; cc.Sprite.prototype.updateDisplayedColor = cc.Sprite.prototype._updateDisplayedColorForWebGL; cc.Sprite.prototype.setDisplayFrame = cc.Sprite.prototype._setDisplayFrameForWebGL; cc.Sprite.prototype.isFrameDisplayed = cc.Sprite.prototype._isFrameDisplayedForWebGL; cc.Sprite.prototype.setBatchNode = cc.Sprite.prototype._setBatchNodeForWebGL; cc.Sprite.prototype.setTexture = cc.Sprite.prototype._setTextureForWebGL; cc.Sprite.prototype.draw = cc.Sprite.prototype._drawForWebGL; }else{ cc.Sprite.prototype._spriteFrameLoadedCallback = cc.Sprite.prototype._spriteFrameLoadedCallbackForCanvas; cc.Sprite.prototype.setOpacityModifyRGB = cc.Sprite.prototype._setOpacityModifyRGBForCanvas; cc.Sprite.prototype.updateDisplayedOpacity = cc.Sprite.prototype._updateDisplayedOpacityForCanvas; cc.Sprite.prototype.ctor = cc.Sprite.prototype._ctorForCanvas; cc.Sprite.prototype.setBlendFunc = cc.Sprite.prototype._setBlendFuncForCanvas; cc.Sprite.prototype.init = cc.Sprite.prototype._initForCanvas; cc.Sprite.prototype.initWithTexture = cc.Sprite.prototype._initWithTextureForCanvas; cc.Sprite.prototype._textureLoadedCallback = cc.Sprite.prototype._textureLoadedCallbackForCanvas; cc.Sprite.prototype.setTextureRect = cc.Sprite.prototype._setTextureRectForCanvas; cc.Sprite.prototype.updateTransform = cc.Sprite.prototype._updateTransformForCanvas; cc.Sprite.prototype.addChild = cc.Sprite.prototype._addChildForCanvas; cc.Sprite.prototype.setOpacity = cc.Sprite.prototype._setOpacityForCanvas; cc.Sprite.prototype.setColor = cc.Sprite.prototype._setColorForCanvas; cc.Sprite.prototype.updateDisplayedColor = cc.Sprite.prototype._updateDisplayedColorForCanvas; cc.Sprite.prototype.setDisplayFrame = cc.Sprite.prototype._setDisplayFrameForCanvas; cc.Sprite.prototype.isFrameDisplayed = cc.Sprite.prototype._isFrameDisplayedForCanvas; cc.Sprite.prototype.setBatchNode = cc.Sprite.prototype._setBatchNodeForCanvas; cc.Sprite.prototype.setTexture = cc.Sprite.prototype._setTextureForCanvas; cc.Sprite.prototype.draw = cc.Sprite.prototype._drawForCanvas; } /** *

* Creates a sprite with an exsiting texture contained in a CCTexture2D object
* After creation, the rect will be the size of the texture, and the offset will be (0,0). *

* @constructs * @param {cc.Texture2D} texture A pointer to an existing CCTexture2D object. You can use a CCTexture2D object for many sprites. * @param {cc.Rect} rect Only the contents inside the rect of this texture will be applied for this sprite. * @return {cc.Sprite} A valid sprite object * @example * //get an image * var img = cc.TextureCache.getInstance().addImage("HelloHTML5World.png"); * * //create a sprite with texture * var sprite1 = cc.Sprite.createWithTexture(img); * * //create a sprite with texture and rect * var sprite2 = cc.Sprite.createWithTexture(img, cc.rect(0,0,480,320)); * */ cc.Sprite.createWithTexture = function (texture, rect) { var argnum = arguments.length; var sprite = new cc.Sprite(); switch (argnum) { case 1: /** Creates an sprite with a texture. The rect used will be the size of the texture. The offset will be (0,0). */ if (sprite && sprite.initWithTexture(texture)) return sprite; return null; break; case 2: /** Creates an sprite with a texture and a rect. The offset will be (0,0). */ if (sprite && sprite.initWithTexture(texture, rect)) return sprite; return null; break; default: throw "Sprite.createWithTexture(): Argument must be non-nil "; break; } }; /** * Create a sprite with filename and rect * @constructs * @param {String} fileName The string which indicates a path to image file, e.g., "scene1/monster.png". * @param {cc.Rect} rect Only the contents inside rect of pszFileName's texture will be applied for this sprite. * @return {cc.Sprite} A valid sprite object * @example * //create a sprite with filename * var sprite1 = cc.Sprite.create("HelloHTML5World.png"); * * //create a sprite with filename and rect * var sprite2 = cc.Sprite.create("HelloHTML5World.png",cc.rect(0,0,480,320)); */ cc.Sprite.create = function (fileName, rect) { var argnum = arguments.length; var sprite = new cc.Sprite(); if (argnum === 0) { if (sprite.init()) return sprite; } else { /** Creates an sprite with an image filename. If the rect equal undefined, the rect used will be the size of the image. The offset will be (0,0). */ if (sprite && sprite.init(fileName, rect)) return sprite; } return null; }; /** *

* Creates a sprite with a sprite frame.
*
* A CCSpriteFrame will be fetched from the CCSpriteFrameCache by pszSpriteFrameName param.
* If the CCSpriteFrame doesn't exist it will raise an exception. *

* @param {String} spriteFrameName A sprite frame which involves a texture and a rect * @return {cc.Sprite} A valid sprite object * @example * * //create a sprite with a sprite frame * var sprite = cc.Sprite.createWithSpriteFrameName('grossini_dance_01.png'); */ cc.Sprite.createWithSpriteFrameName = function (spriteFrameName) { var spriteFrame = null; if (typeof(spriteFrameName) == 'string') { spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame(spriteFrameName); if (!spriteFrame) { cc.log("Invalid spriteFrameName: " + spriteFrameName); return null; } } else { cc.log("Invalid argument. Expecting string."); return null; } var sprite = new cc.Sprite(); if (sprite && sprite.initWithSpriteFrame(spriteFrame)) { return sprite; } return null; }; /** *

* Creates a sprite with a sprite frame.
*
* A CCSpriteFrame will be fetched from the CCSpriteFrameCache by pszSpriteFrameName param.
* If the CCSpriteFrame doesn't exist it will raise an exception. *

* @param {cc.SpriteFrame} spriteFrame A sprite frame which involves a texture and a rect * @return {cc.Sprite} A valid sprite object * @example * //get a sprite frame * var spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame("grossini_dance_01.png"); * * //create a sprite with a sprite frame * var sprite = cc.Sprite.createWithSpriteFrame(spriteFrame); */ cc.Sprite.createWithSpriteFrame = function (spriteFrame) { var sprite = new cc.Sprite(); if (sprite && sprite.initWithSpriteFrame(spriteFrame)) { return sprite; } return null; };