1 /****************************************************************************
  2  Copyright (c) 2008-2010 Ricardo Quesada
  3  Copyright (c) 2011-2012 cocos2d-x.org
  4  Copyright (c) 2013-2014 Chukong Technologies Inc.
  5  Copyright (c) 2012 Neofect. All rights reserved.
  6 
  7  http://www.cocos2d-x.org
  8 
  9  Permission is hereby granted, free of charge, to any person obtaining a copy
 10  of this software and associated documentation files (the "Software"), to deal
 11  in the Software without restriction, including without limitation the rights
 12  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 13  copies of the Software, and to permit persons to whom the Software is
 14  furnished to do so, subject to the following conditions:
 15 
 16  The above copyright notice and this permission notice shall be included in
 17  all copies or substantial portions of the Software.
 18 
 19  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 20  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 21  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 22  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 23  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 24  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 25  THE SOFTWARE.
 26 
 27  Created by Jung Sang-Taik on 2012-03-16
 28  ****************************************************************************/
 29 
 30 /**
 31  * <p>
 32  * A 9-slice sprite for cocos2d UI.                                                                    <br/>
 33  *                                                                                                     <br/>
 34  * 9-slice scaling allows you to specify how scaling is applied                                        <br/>
 35  * to specific areas of a sprite. With 9-slice scaling (3x3 grid),                                     <br/>
 36  * you can ensure that the sprite does not become distorted when                                       <br/>
 37  * scaled.                                                                                             <br/>
 38  * @note: it will refactor in v3.1                                                                    <br/>
 39  * @see http://yannickloriot.com/library/ios/cccontrolextension/Classes/CCScale9Sprite.html            <br/>
 40  * </p>
 41  * @class
 42  * @extends cc.Node
 43  *
 44  * @property {cc.Size}  preferredSize   - The preferred size of the 9-slice sprite
 45  * @property {cc.Rect}  capInsets       - The cap insets of the 9-slice sprite
 46  * @property {Number}   insetLeft       - The left inset of the 9-slice sprite
 47  * @property {Number}   insetTop        - The top inset of the 9-slice sprite
 48  * @property {Number}   insetRight      - The right inset of the 9-slice sprite
 49  * @property {Number}   insetBottom     - The bottom inset of the 9-slice sprite
 50  */
 51 
 52 ccui.Scale9Sprite = cc.Scale9Sprite = cc.Node.extend(/** @lends ccui.Scale9Sprite# */{
 53     _spriteRect: null,
 54     _capInsetsInternal: null,
 55     _positionsAreDirty: false,
 56 
 57     _scale9Image: null,
 58     _topLeft: null,
 59     _top: null,
 60     _topRight: null,
 61     _left: null,
 62     _centre: null,
 63     _right: null,
 64     _bottomLeft: null,
 65     _bottom: null,
 66     _bottomRight: null,
 67 
 68     _scale9Enabled: true,
 69     _brightState: 0,
 70     _renderers: null,
 71 
 72     _opacityModifyRGB: false,
 73 
 74     _originalSize: null,
 75     _preferredSize: null,
 76     _opacity: 0,
 77     _color: null,
 78     _capInsets: null,
 79     _insetLeft: 0,
 80     _insetTop: 0,
 81     _insetRight: 0,
 82     _insetBottom: 0,
 83 
 84     _spritesGenerated: false,
 85     _spriteFrameRotated: false,
 86     _textureLoaded:false,
 87     _className:"Scale9Sprite",
 88 
 89     //v3.3
 90     _flippedX: false,
 91     _flippedY: false,
 92 
 93     /**
 94      * return  texture is loaded
 95      * @returns {boolean}
 96      */
 97     textureLoaded:function(){
 98         return this._textureLoaded;
 99     },
100 
101     /**
102      * add texture loaded event listener
103      * @param {Function} callback
104      * @param {Object} target
105      * @deprecated since 3.1, please use addEventListener instead
106      */
107     addLoadedEventListener:function(callback, target){
108         this.addEventListener("load", callback, target);
109     },
110 
111     _updateCapInset: function () {
112         var insets, locInsetLeft = this._insetLeft, locInsetTop = this._insetTop, locInsetRight = this._insetRight;
113         var locSpriteRect = this._spriteRect, locInsetBottom = this._insetBottom;
114         if (locInsetLeft === 0 && locInsetTop === 0 && locInsetRight === 0 && locInsetBottom === 0) {
115             insets = cc.rect(0, 0, 0, 0);
116         } else {
117             insets = this._spriteFrameRotated ? cc.rect(locInsetBottom, locInsetLeft,
118                     locSpriteRect.width - locInsetRight - locInsetLeft,
119                     locSpriteRect.height - locInsetTop - locInsetBottom) :
120                 cc.rect(locInsetLeft, locInsetTop,
121                         locSpriteRect.width - locInsetLeft - locInsetRight,
122                         locSpriteRect.height - locInsetTop - locInsetBottom);
123         }
124         this.setCapInsets(insets);
125     },
126 
127     _updatePositions: function () {
128         // Check that instances are non-NULL
129         if (!((this._topLeft) && (this._topRight) && (this._bottomRight) &&
130             (this._bottomLeft) && (this._centre))) {
131             // if any of the above sprites are NULL, return
132             return;
133         }
134 
135         var size = this._contentSize;
136         var locTopLeft = this._topLeft, locTopRight = this._topRight, locBottomRight = this._bottomRight, locBottomLeft = this._bottomLeft;
137         var locLeft = this._left, locRight = this._right, locTop = this._top, locBottom = this._bottom;
138         var locCenter = this._centre, locCenterContentSize = this._centre.getContentSize();
139         var locTopLeftContentSize = locTopLeft.getContentSize();
140         var locBottomLeftContentSize = locBottomLeft.getContentSize();
141 
142         var sizableWidth = size.width - locTopLeftContentSize.width - locTopRight.getContentSize().width;
143         var sizableHeight = size.height - locTopLeftContentSize.height - locBottomRight.getContentSize().height;
144 
145         var horizontalScale = sizableWidth / locCenterContentSize.width;
146         var verticalScale = sizableHeight / locCenterContentSize.height;
147 
148         var rescaledWidth = locCenterContentSize.width * horizontalScale;
149         var rescaledHeight = locCenterContentSize.height * verticalScale;
150 
151         var leftWidth = locBottomLeftContentSize.width;
152         var bottomHeight = locBottomLeftContentSize.height;
153         var centerOffset = cc.p(this._offset.x * horizontalScale, this._offset.y*verticalScale);
154 
155         if (cc._renderType === cc.game.RENDER_TYPE_WEBGL) {
156             //browser is in canvas mode, need to manually control rounding to prevent overlapping pixels
157             var roundedRescaledWidth = Math.round(rescaledWidth);
158             if (rescaledWidth !== roundedRescaledWidth) {
159                 rescaledWidth = roundedRescaledWidth;
160                 horizontalScale = rescaledWidth / locCenterContentSize.width;
161             }
162             var roundedRescaledHeight = Math.round(rescaledHeight);
163             if (rescaledHeight !== roundedRescaledHeight) {
164                 rescaledHeight = roundedRescaledHeight;
165                 verticalScale = rescaledHeight / locCenterContentSize.height;
166             }
167         }
168 
169         locCenter.setScaleX(horizontalScale);
170         locCenter.setScaleY(verticalScale);
171 
172         locBottomLeft.setAnchorPoint(1, 1);
173         locBottomLeft.setPosition(leftWidth,bottomHeight);
174 
175         locBottomRight.setAnchorPoint(0, 1);
176         locBottomRight.setPosition(leftWidth+rescaledWidth,bottomHeight);
177 
178 
179         locTopLeft.setAnchorPoint(1, 0);
180         locTopLeft.setPosition(leftWidth, bottomHeight+rescaledHeight);
181 
182         locTopRight.setAnchorPoint(0, 0);
183         locTopRight.setPosition(leftWidth+rescaledWidth, bottomHeight+rescaledHeight);
184 
185         locLeft.setAnchorPoint(1, 0.5);
186         locLeft.setPosition(leftWidth, bottomHeight+rescaledHeight/2 + centerOffset.y);
187         locLeft.setScaleY(verticalScale);
188 
189         locRight.setAnchorPoint(0, 0.5);
190         locRight.setPosition(leftWidth+rescaledWidth,bottomHeight+rescaledHeight/2 + centerOffset.y);
191         locRight.setScaleY(verticalScale);
192 
193         locTop.setAnchorPoint(0.5, 0);
194         locTop.setPosition(leftWidth+rescaledWidth/2 + centerOffset.x,bottomHeight+rescaledHeight);
195         locTop.setScaleX(horizontalScale);
196 
197         locBottom.setAnchorPoint(0.5, 1);
198         locBottom.setPosition(leftWidth+rescaledWidth/2 + centerOffset.x,bottomHeight);
199         locBottom.setScaleX(horizontalScale);
200 
201         locCenter.setAnchorPoint(0.5, 0.5);
202         locCenter.setPosition(leftWidth+rescaledWidth/2 + centerOffset.x, bottomHeight+rescaledHeight/2 + centerOffset.y);
203         locCenter.setScaleX(horizontalScale);
204         locCenter.setScaleY(verticalScale);
205     },
206 
207     /**
208      * Constructor function. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
209      * @function
210      * @param {string|cc.SpriteFrame} file file name of texture or a SpriteFrame
211      * @param {cc.Rect} rectOrCapInsets
212      * @param {cc.Rect} capInsets
213      * @returns {Scale9Sprite}
214      */
215     ctor: function (file, rectOrCapInsets, capInsets) {
216         cc.Node.prototype.ctor.call(this);
217         this._spriteRect = cc.rect(0, 0, 0, 0);
218         this._capInsetsInternal = cc.rect(0, 0, 0, 0);
219 
220         this._originalSize = cc.size(0, 0);
221         this._preferredSize = cc.size(0, 0);
222         this._capInsets = cc.rect(0, 0, 0, 0);
223         this._renderers = [];
224 
225         if(file != undefined){
226             if(file instanceof cc.SpriteFrame)
227                 this.initWithSpriteFrame(file, rectOrCapInsets);
228             else{
229                 var frame = cc.spriteFrameCache.getSpriteFrame(file);
230                 if(frame != null)
231                     this.initWithSpriteFrame(frame, rectOrCapInsets);
232                 else
233                     this.initWithFile(file, rectOrCapInsets, capInsets);
234             }
235         }else{
236             this.init();
237         }
238     },
239 
240     getSprite: function () {
241         return this._scale9Image;
242     },
243 
244     /** Original sprite's size. */
245     getOriginalSize: function () {
246         return cc.size(this._originalSize);
247     },
248 
249     //if the preferredSize component is given as -1, it is ignored
250     getPreferredSize: function () {
251         return cc.size(this._preferredSize);
252     },
253     _getPreferredWidth: function () {
254         return this._preferredSize.width;
255     },
256     _getPreferredHeight: function () {
257         return this._preferredSize.height;
258     },
259     setPreferredSize: function (preferredSize) {
260         this.setContentSize(preferredSize);
261         this._preferredSize = preferredSize;
262 
263         if (this._positionsAreDirty) {
264             this._updatePositions();
265             this._positionsAreDirty = false;
266             this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
267         }
268     },
269     _setPreferredWidth: function (value) {
270         this._setWidth(value);
271         this._preferredSize.width = value;
272     },
273     _setPreferredHeight: function (value) {
274         this._setHeight(value);
275         this._preferredSize.height = value;
276     },
277 
278     /** Opacity: conforms to CCRGBAProtocol protocol */
279     setOpacity: function (opacity) {
280         cc.Node.prototype.setOpacity.call(this, opacity);
281         if(this._scale9Enabled) {
282             var pChildren = this._renderers;
283             for(var i=0; i<pChildren.length; i++)
284                 pChildren[i].setOpacity(opacity);
285         }
286         else if(this._scale9Image)
287             this._scale9Image.setOpacity(opacity);
288         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
289     },
290 
291     /** Color: conforms to CCRGBAProtocol protocol */
292     setColor: function (color) {
293         cc.Node.prototype.setColor.call(this, color);
294         if(this._scale9Enabled) {
295             var scaleChildren = this._renderers;
296             for (var i = 0; i < scaleChildren.length; i++) {
297                 var selChild = scaleChildren[i];
298                 if (selChild)
299                     selChild.setColor(color);
300             }
301         }
302         else if (this._scale9Image)
303             this._scale9Image.setColor(color);
304         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
305     },
306 
307     getCapInsets: function () {
308         return cc.rect(this._capInsets);
309     },
310 
311     setCapInsets: function (capInsets) {
312         var contentSize = this._contentSize;
313         var tempWidth = contentSize.width, tempHeight = contentSize.height;
314 
315         this.updateWithSprite(  this._scale9Image,
316                                 this._spriteRect,
317                                 this._spriteFrameRotated,
318                                 this._offset,
319                                 this._originalSize,
320                                 capInsets );
321         this._insetLeft = capInsets.x;
322         this._insetTop = capInsets.y;
323         this._insetRight = this._originalSize.width - this._insetLeft - capInsets.width;
324         this._insetBottom = this._originalSize.height - this._insetTop - capInsets.height;
325         //restore the contentSize
326         this.setContentSize(tempWidth, tempHeight);
327     },
328 
329     /**
330      * Gets the left side inset
331      * @returns {number}
332      */
333     getInsetLeft: function () {
334         return this._insetLeft;
335     },
336 
337     /**
338      * Sets the left side inset
339      * @param {Number} insetLeft
340      */
341     setInsetLeft: function (insetLeft) {
342         this._insetLeft = insetLeft;
343         this._updateCapInset();
344     },
345 
346     /**
347      * Gets the top side inset
348      * @returns {number}
349      */
350     getInsetTop: function () {
351         return this._insetTop;
352     },
353 
354     /**
355      * Sets the top side inset
356      * @param {Number} insetTop
357      */
358     setInsetTop: function (insetTop) {
359         this._insetTop = insetTop;
360         this._updateCapInset();
361     },
362 
363     /**
364      * Gets the right side inset
365      * @returns {number}
366      */
367     getInsetRight: function () {
368         return this._insetRight;
369     },
370     /**
371      * Sets the right side inset
372      * @param {Number} insetRight
373      */
374     setInsetRight: function (insetRight) {
375         this._insetRight = insetRight;
376         this._updateCapInset();
377     },
378 
379     /**
380      * Gets the bottom side inset
381      * @returns {number}
382      */
383     getInsetBottom: function () {
384         return this._insetBottom;
385     },
386     /**
387      * Sets the bottom side inset
388      * @param {number} insetBottom
389      */
390     setInsetBottom: function (insetBottom) {
391         this._insetBottom = insetBottom;
392         this._updateCapInset();
393     },
394 
395     /**
396      * Sets the untransformed size of the Scale9Sprite.
397      * @override
398      * @param {cc.Size|Number} size The untransformed size of the Scale9Sprite or The untransformed size's width of the Scale9Sprite.
399      * @param {Number} [height] The untransformed size's height of the Scale9Sprite.
400      */
401     setContentSize: function (size, height) {
402         cc.Node.prototype.setContentSize.call(this, size, height);
403         this._positionsAreDirty = true;
404     },
405 
406     setAnchorPoint: function (point, y) {
407         cc.Node.prototype.setAnchorPoint.call(this, point, y);
408         if(!this._scale9Enabled) {
409             if(this._scale9Image) {
410                 this._scale9Image.setAnchorPoint(point, y);
411                 this._positionsAreDirty = true;
412             }
413         }
414     },
415     _setWidth: function (value) {
416         cc.Node.prototype._setWidth.call(this, value);
417         this._positionsAreDirty = true;
418     },
419 
420     _setHeight: function (value) {
421         cc.Node.prototype._setHeight.call(this, value);
422         this._positionsAreDirty = true;
423     },
424 
425     /**
426      * Initializes a ccui.Scale9Sprite. please do not call this function by yourself, you should pass the parameters to constructor to initialize it.
427      * @returns {boolean}
428      */
429     init: function () {
430         return this.initWithBatchNode(null, cc.rect(0, 0, 0, 0), false, cc.rect(0, 0, 0, 0));
431     },
432 
433     /**
434      * Initializes a 9-slice sprite with a SpriteBatchNode.
435      * @param {cc.SpriteBatchNode} batchNode
436      * @param {cc.Rect} rect
437      * @param {boolean|cc.Rect} rotated
438      * @param {cc.Rect} [capInsets]
439      * @returns {boolean}
440      */
441     initWithBatchNode: function (batchNode, rect, rotated, capInsets) {
442         if (capInsets === undefined) {
443             capInsets = rotated;
444             rotated = false;
445         }
446 
447         if (batchNode)
448             this.updateWithBatchNode(batchNode, rect, rotated, capInsets);
449 
450         this.setCascadeColorEnabled(true);
451         this.setCascadeOpacityEnabled(true);
452         this.setAnchorPoint(0.5, 0.5);
453         this._positionsAreDirty = true;
454         return true;
455     },
456 
457     /**
458      * Initializes a 9-slice sprite with a texture file, a delimitation zone and
459      * with the specified cap insets.
460      * Once the sprite is created, you can then call its "setContentSize:" method
461      * to resize the sprite will all it's 9-slice goodness intact.
462      * It respects the anchorPoint too.
463      *
464      * @param {String} file The name of the texture file.
465      * @param {cc.Rect} rect The rectangle that describes the sub-part of the texture that
466      * is the whole image. If the shape is the whole texture, set this to the texture's full rect.
467      * @param {cc.Rect} capInsets The values to use for the cap insets.
468      */
469     initWithFile: function (file, rect, capInsets) {
470         if (file instanceof cc.Rect) {
471             file = arguments[1];
472             capInsets = arguments[0];
473             rect = cc.rect(0, 0, 0, 0);
474         } else {
475             rect = rect || cc.rect(0, 0, 0, 0);
476             capInsets = capInsets || cc.rect(0, 0, 0, 0);
477         }
478 
479         if(!file)
480             throw new Error("ccui.Scale9Sprite.initWithFile(): file should be non-null");
481 
482         var texture = cc.textureCache.getTextureForKey(file);
483         if (!texture) {
484             texture = cc.textureCache.addImage(file);
485         }
486 
487         var locLoaded = texture.isLoaded();
488         this._textureLoaded = locLoaded;
489         if(!locLoaded){
490             texture.addEventListener("load", function(sender){
491                 // the texture is rotated on Canvas render mode, so isRotated always is false.
492                 var preferredSize = this._preferredSize, restorePreferredSize = preferredSize.width !== 0 && preferredSize.height !== 0;
493                 if (restorePreferredSize) preferredSize = cc.size(preferredSize.width, preferredSize.height);
494                 var size  = sender.getContentSize();
495                 this.updateWithBatchNode(this._scale9Image, cc.rect(0,0,size.width,size.height), false, this._capInsets);
496                 if (restorePreferredSize)this.setPreferredSize(preferredSize);
497                 this._positionsAreDirty = true;
498                 this.setNodeDirty();
499                 this.dispatchEvent("load");
500             }, this);
501         }
502 
503         return this.initWithBatchNode(new cc.SpriteBatchNode(file, 9), rect, false, capInsets);
504     },
505 
506     /**
507      * Initializes a 9-slice sprite with an sprite frame and with the specified
508      * cap insets.
509      * Once the sprite is created, you can then call its "setContentSize:" method
510      * to resize the sprite will all it's 9-slice goodness interact.
511      * It respects the anchorPoint too.
512      *
513      * @param spriteFrame The sprite frame object.
514      * @param capInsets The values to use for the cap insets.
515      */
516     initWithSpriteFrame: function (spriteFrame, capInsets) {
517         if(!spriteFrame || !spriteFrame.getTexture())
518             throw new Error("ccui.Scale9Sprite.initWithSpriteFrame(): spriteFrame should be non-null and its texture should be non-null");
519 
520         capInsets = capInsets || cc.rect(0, 0, 0, 0);
521         var locLoaded = spriteFrame.textureLoaded();
522         this._textureLoaded = locLoaded;
523         if(!locLoaded){
524             spriteFrame.addEventListener("load", function(sender){
525                 // the texture is rotated on Canvas render mode, so isRotated always is false.
526                 var preferredSize = this._preferredSize, restorePreferredSize = preferredSize.width !== 0 && preferredSize.height !== 0;
527                 if (restorePreferredSize) preferredSize = cc.size(preferredSize.width, preferredSize.height);
528                 this.updateWithBatchNode(this._scale9Image, sender.getRect(), cc._renderType === cc.game.RENDER_TYPE_WEBGL && sender.isRotated(), this._capInsets);
529                 if (restorePreferredSize)this.setPreferredSize(preferredSize);
530                 this._positionsAreDirty = true;
531                 this.setNodeDirty();
532                 this.dispatchEvent("load");
533             },this);
534         }
535         var batchNode = new cc.SpriteBatchNode(spriteFrame.getTexture(), 9);
536         // the texture is rotated on Canvas render mode, so isRotated always is false.
537         return this.initWithBatchNode(batchNode, spriteFrame.getRect(), cc._renderType === cc.game.RENDER_TYPE_WEBGL && spriteFrame.isRotated(), capInsets);
538     },
539 
540     /**
541      * Initializes a 9-slice sprite with an sprite frame name and with the specified
542      * cap insets.
543      * Once the sprite is created, you can then call its "setContentSize:" method
544      * to resize the sprite will all it's 9-slice goodness interact.
545      * It respects the anchorPoint too.
546      *
547      * @param spriteFrameName The sprite frame name.
548      * @param capInsets The values to use for the cap insets.
549      */
550     initWithSpriteFrameName: function (spriteFrameName, capInsets) {
551         if(!spriteFrameName)
552             throw new Error("ccui.Scale9Sprite.initWithSpriteFrameName(): spriteFrameName should be non-null");
553         capInsets = capInsets || cc.rect(0, 0, 0, 0);
554 
555         var frame = cc.spriteFrameCache.getSpriteFrame(spriteFrameName);
556         if (frame == null) {
557             cc.log("ccui.Scale9Sprite.initWithSpriteFrameName(): can't find the sprite frame by spriteFrameName");
558             return false;
559         }
560 
561         return this.initWithSpriteFrame(frame, capInsets);
562     },
563 
564     /**
565      * Creates and returns a new sprite object with the specified cap insets.
566      * You use this method to add cap insets to a sprite or to change the existing
567      * cap insets of a sprite. In both cases, you get back a new image and the
568      * original sprite remains untouched.
569      *
570      * @param {cc.Rect} capInsets The values to use for the cap insets.
571      */
572     resizableSpriteWithCapInsets: function (capInsets) {
573         var pReturn = new ccui.Scale9Sprite();
574         if (pReturn && pReturn.initWithBatchNode(this._scale9Image, this._spriteRect, false, capInsets))
575             return pReturn;
576         return null;
577     },
578 
579     /** sets the premultipliedAlphaOpacity property.
580      If set to NO then opacity will be applied as: glColor(R,G,B,opacity);
581      If set to YES then opacity will be applied as: glColor(opacity, opacity, opacity, opacity );
582      Textures with premultiplied alpha will have this property by default on YES. Otherwise the default value is NO
583      @since v0.8
584      */
585     setOpacityModifyRGB: function (value) {
586         if(!this._scale9Image)
587             return;
588         this._opacityModifyRGB = value;
589         var scaleChildren = this._scale9Image.getChildren();
590         if (scaleChildren) {
591             for (var i = 0, len = scaleChildren.length; i < len; i++)
592                 scaleChildren[i].setOpacityModifyRGB(value);
593         }
594         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
595     },
596 
597     /** returns whether or not the opacity will be applied using glColor(R,G,B,opacity) or glColor(opacity, opacity, opacity, opacity);
598      @since v0.8
599      */
600     isOpacityModifyRGB: function () {
601         return this._opacityModifyRGB;
602     },
603 
604     createSlicedSprites: function() {
605         var width = this._originalSize.width,
606             height = this._originalSize.height;
607         var originalRect = this._spriteRect;
608         var offsetX = Math.floor(this._offset.x + (width - originalRect.width) / 2.0);
609         var offsetY = Math.floor(this._offset.y + (height - originalRect.height) / 2.0);
610         var sx = originalRect.x,
611             sy = originalRect.y;
612         var capInsetsInternal = this._capInsetsInternal;
613         var locScale9Image = this._scale9Image;
614         var selTexture = locScale9Image.getTexture();
615         var rotated = this._spriteFrameRotated;
616         var rect = cc.rect(originalRect.x, originalRect.y, originalRect.width, originalRect.height);
617 
618         if(cc._rectEqualToZero(capInsetsInternal))
619             capInsetsInternal = cc.rect(width /3, height /3, width /3, height /3);
620 
621         if(this._spriteFrameRotated) {
622             sx -= offsetY;  sy -= offsetX;
623         }else{
624             sx -= offsetX;  sy -= offsetY;
625         }
626         originalRect = cc.rect(sx, sy, width, height);
627 
628         var leftWidth = capInsetsInternal.x,
629             centerWidth = capInsetsInternal.width,
630             rightWidth = originalRect.width - (leftWidth + centerWidth),
631             topHeight = capInsetsInternal.y,
632             centerHeight = capInsetsInternal.height,
633             bottomHeight = originalRect.height - (topHeight + centerHeight);
634 
635 
636         var x = 0.0, y = 0.0;
637 
638         // top left
639         var leftTopBoundsOriginal = cc.rect(x + 0.5 | 0, y + 0.5 | 0, leftWidth + 0.5 | 0, topHeight + 0.5 | 0);
640         var leftTopBounds = leftTopBoundsOriginal;
641 
642         // top center
643         x += leftWidth;
644         var centerTopBoundsOriginal = cc.rect(x + 0.5 | 0, y + 0.5 | 0, centerWidth + 0.5 | 0, topHeight + 0.5 | 0);
645         var centerTopBounds = centerTopBoundsOriginal;
646 
647         // top right
648         x += centerWidth;
649         var  rightTopBoundsOriginal = cc.rect(x + 0.5 | 0, y + 0.5 | 0, rightWidth + 0.5 | 0, topHeight + 0.5 | 0);
650         var  rightTopBounds = rightTopBoundsOriginal;
651 
652         // ... center row
653         x = 0.0;
654         y = 0.0;
655         y += topHeight;
656 
657         // center left
658         var leftCenterBounds = cc.rect(x + 0.5 | 0, y + 0.5 | 0, leftWidth + 0.5 | 0, centerHeight + 0.5 | 0);
659 
660         // center center
661         x += leftWidth;
662         var centerBoundsOriginal = cc.rect(x + 0.5 | 0, y + 0.5 | 0, centerWidth + 0.5 | 0, centerHeight + 0.5 | 0);
663         var centerBounds = centerBoundsOriginal;
664 
665         // center right
666         x += centerWidth;
667         var rightCenterBounds = cc.rect(x + 0.5 | 0, y + 0.5 | 0, rightWidth + 0.5 | 0, centerHeight + 0.5 | 0);
668 
669         // ... bottom row
670         x = 0.0;
671         y = 0.0;
672         y += topHeight;
673         y += centerHeight;
674 
675         // bottom left
676         var leftBottomBounds = cc.rect(x + 0.5 | 0, y + 0.5 | 0, leftWidth + 0.5 | 0, bottomHeight + 0.5 | 0);
677 
678         // bottom center
679         x += leftWidth;
680         var centerBottomBounds = cc.rect(x + 0.5 | 0, y + 0.5 | 0, centerWidth + 0.5 | 0, bottomHeight + 0.5 | 0);
681 
682         // bottom right
683         x += centerWidth;
684         var rightBottomBoundsOriginal = cc.rect(x + 0.5 | 0, y + 0.5 | 0, rightWidth + 0.5 | 0, bottomHeight + 0.5 | 0);
685         var rightBottomBounds = rightBottomBoundsOriginal;
686 
687         var rotatedLeftTopBoundsOriginal = leftTopBoundsOriginal;
688         var rotatedCenterBoundsOriginal = centerBoundsOriginal;
689         var rotatedRightBottomBoundsOriginal = rightBottomBoundsOriginal;
690 
691         var rotatedCenterBounds = centerBounds;
692         var rotatedRightBottomBounds = rightBottomBounds;
693         var rotatedLeftBottomBounds = leftBottomBounds;
694         var rotatedRightTopBounds = rightTopBounds;
695         var rotatedLeftTopBounds = leftTopBounds;
696         var rotatedRightCenterBounds = rightCenterBounds;
697         var rotatedLeftCenterBounds = leftCenterBounds;
698         var rotatedCenterBottomBounds = centerBottomBounds;
699         var rotatedCenterTopBounds = centerTopBounds;
700 
701         var t = cc.affineTransformMakeIdentity();
702         if (!rotated) {
703             t = cc.affineTransformTranslate(t, rect.x, rect.y);
704         
705             rotatedLeftTopBoundsOriginal = cc.rectApplyAffineTransform(rotatedLeftTopBoundsOriginal, t);
706             rotatedCenterBoundsOriginal = cc.rectApplyAffineTransform(rotatedCenterBoundsOriginal, t);
707             rotatedRightBottomBoundsOriginal = cc.rectApplyAffineTransform(rotatedRightBottomBoundsOriginal, t);
708         
709             rotatedCenterBounds = cc.rectApplyAffineTransform(rotatedCenterBounds, t);
710             rotatedRightBottomBounds = cc.rectApplyAffineTransform(rotatedRightBottomBounds, t);
711             rotatedLeftBottomBounds = cc.rectApplyAffineTransform(rotatedLeftBottomBounds, t);
712             rotatedRightTopBounds = cc.rectApplyAffineTransform(rotatedRightTopBounds, t);
713             rotatedLeftTopBounds = cc.rectApplyAffineTransform(rotatedLeftTopBounds, t);
714             rotatedRightCenterBounds = cc.rectApplyAffineTransform(rotatedRightCenterBounds, t);
715             rotatedLeftCenterBounds = cc.rectApplyAffineTransform(rotatedLeftCenterBounds, t);
716             rotatedCenterBottomBounds = cc.rectApplyAffineTransform(rotatedCenterBottomBounds, t);
717             rotatedCenterTopBounds = cc.rectApplyAffineTransform(rotatedCenterTopBounds, t);
718 
719         } else {
720             t = cc.affineTransformTranslate(t, rect.height + rect.x, rect.y);
721             t = cc.affineTransformRotate(t, 1.57079633);
722         
723             leftTopBoundsOriginal = cc.rectApplyAffineTransform(leftTopBoundsOriginal, t);
724             centerBoundsOriginal = cc.rectApplyAffineTransform(centerBoundsOriginal, t);
725             rightBottomBoundsOriginal = cc.rectApplyAffineTransform(rightBottomBoundsOriginal, t);
726         
727             centerBounds = cc.rectApplyAffineTransform(centerBounds, t);
728             rightBottomBounds = cc.rectApplyAffineTransform(rightBottomBounds, t);
729             leftBottomBounds = cc.rectApplyAffineTransform(leftBottomBounds, t);
730             rightTopBounds = cc.rectApplyAffineTransform(rightTopBounds, t);
731             leftTopBounds = cc.rectApplyAffineTransform(leftTopBounds, t);
732             rightCenterBounds = cc.rectApplyAffineTransform(rightCenterBounds, t);
733             leftCenterBounds = cc.rectApplyAffineTransform(leftCenterBounds, t);
734             centerBottomBounds = cc.rectApplyAffineTransform(centerBottomBounds, t);
735             centerTopBounds = cc.rectApplyAffineTransform(centerTopBounds, t);
736         
737             rotatedLeftTopBoundsOriginal.x = leftTopBoundsOriginal.x;
738             rotatedCenterBoundsOriginal.x = centerBoundsOriginal.x;
739             rotatedRightBottomBoundsOriginal.x = rightBottomBoundsOriginal.x;
740         
741             rotatedCenterBounds.x = centerBounds.x;
742             rotatedRightBottomBounds.x = rightBottomBounds.x;
743             rotatedLeftBottomBounds.x = leftBottomBounds.x;
744             rotatedRightTopBounds.x = rightTopBounds.x;
745             rotatedLeftTopBounds.x = leftTopBounds.x;
746             rotatedRightCenterBounds.x = rightCenterBounds.x;
747             rotatedLeftCenterBounds.x = leftCenterBounds.x;
748             rotatedCenterBottomBounds.x = centerBottomBounds.x;
749             rotatedCenterTopBounds.x = centerTopBounds.x;
750         
751         
752             rotatedLeftTopBoundsOriginal.y = leftTopBoundsOriginal.y;
753             rotatedCenterBoundsOriginal.y = centerBoundsOriginal.y;
754             rotatedRightBottomBoundsOriginal.y = rightBottomBoundsOriginal.y;
755         
756             rotatedCenterBounds.y = centerBounds.y;
757             rotatedRightBottomBounds.y = rightBottomBounds.y;
758             rotatedLeftBottomBounds.y = leftBottomBounds.y;
759             rotatedRightTopBounds.y = rightTopBounds.y;
760             rotatedLeftTopBounds.y = leftTopBounds.y;
761             rotatedRightCenterBounds.y = rightCenterBounds.y;
762             rotatedLeftCenterBounds.y = leftCenterBounds.y;
763             rotatedCenterBottomBounds.y = centerBottomBounds.y;
764             rotatedCenterTopBounds.y = centerTopBounds.y;
765         }
766 
767         // Centre
768         if(!this._centre)
769             this._centre = new cc.Sprite();
770         this._centre.initWithTexture(selTexture, rotatedCenterBounds, rotated);
771         if(rotatedCenterBounds.width > 0 && rotatedCenterBounds.height > 0 )
772             this._renderers.push(this._centre);
773 
774         // Top
775         if(!this._top)
776             this._top = new cc.Sprite();
777         this._top.initWithTexture(selTexture, rotatedCenterTopBounds, rotated);
778         if(rotatedCenterTopBounds.width > 0 && rotatedCenterTopBounds.height > 0 )
779             this._renderers.push(this._top);
780 
781         // Bottom
782         if(!this._bottom)
783             this._bottom = new cc.Sprite();
784         this._bottom.initWithTexture(selTexture, rotatedCenterBottomBounds, rotated);
785         if(rotatedCenterBottomBounds.width > 0 && rotatedCenterBottomBounds.height > 0 )
786             this._renderers.push(this._bottom);
787 
788         // Left
789         if(!this._left)
790             this._left = new cc.Sprite();
791         this._left.initWithTexture(selTexture, rotatedLeftCenterBounds, rotated);
792         if(rotatedLeftCenterBounds.width > 0 && rotatedLeftCenterBounds.height > 0 )
793             this._renderers.push(this._left);
794 
795         // Right
796         if(!this._right)
797             this._right = new cc.Sprite();
798         this._right.initWithTexture(selTexture, rotatedRightCenterBounds, rotated);
799         if(rotatedRightCenterBounds.width > 0 && rotatedRightCenterBounds.height > 0 )
800             this._renderers.push(this._right);
801 
802         // Top left
803         if(!this._topLeft)
804             this._topLeft = new cc.Sprite();
805         this._topLeft.initWithTexture(selTexture, rotatedLeftTopBounds, rotated);
806         if(rotatedLeftTopBounds.width > 0 && rotatedLeftTopBounds.height > 0 )
807             this._renderers.push(this._topLeft);
808 
809         // Top right
810         if(!this._topRight)
811             this._topRight = new cc.Sprite();
812         this._topRight.initWithTexture(selTexture, rotatedRightTopBounds, rotated);
813         if(rotatedRightTopBounds.width > 0 && rotatedRightTopBounds.height > 0 )
814             this._renderers.push(this._topRight);
815 
816         // Bottom left
817         if(!this._bottomLeft)
818             this._bottomLeft = new cc.Sprite();
819         this._bottomLeft.initWithTexture(selTexture, rotatedLeftBottomBounds, rotated);
820         if(rotatedLeftBottomBounds.width > 0 && rotatedLeftBottomBounds.height > 0 )
821             this._renderers.push(this._bottomLeft);
822 
823         // Bottom right
824         if(!this._bottomRight)
825             this._bottomRight = new cc.Sprite();
826         this._bottomRight.initWithTexture(selTexture, rotatedRightBottomBounds, rotated);
827         if(rotatedRightBottomBounds.width > 0 && rotatedRightBottomBounds.height > 0 )
828             this._renderers.push(this._bottomRight);
829     },
830     /**
831      * @brief Update Scale9Sprite with a specified sprite.
832      *
833      * @param sprite A sprite pointer.
834      * @param rect A delimitation zone.
835      * @param rotated Whether the sprite is rotated or not.
836      * @param offset The offset when slice the sprite.
837      * @param originalSize The origial size of the sprite.
838      * @param capInsets The Values to use for the cap insets.
839      * @return True if update success, false otherwise.
840      */
841     updateWithSprite: function(sprite, spriteRect, spriteFrameRotated, offset, originalSize, capInsets) {
842         var opacity = this.getOpacity();
843         var color = this.getColor();
844         this._renderers.length = 0;
845         if(sprite) {
846             if(!sprite.getSpriteFrame())
847                 return false;
848             if(!this._scale9Image)
849                 this._scale9Image = sprite;
850         }
851         if(!this._scale9Image)  return false;
852         var rect = spriteRect;
853         var size = originalSize;
854 
855         var tmpTexture = this._scale9Image.getTexture();
856         var locLoaded = tmpTexture && tmpTexture.isLoaded();
857         this._textureLoaded = locLoaded;
858         if(!locLoaded){
859             tmpTexture.addEventListener("load", function(sender){
860                 this._positionsAreDirty = true;
861                 this.updateWithSprite(sprite, spriteRect, spriteFrameRotated, offset, originalSize, capInsets);
862                 this.setVisible(true);
863                 this.setNodeDirty();
864                 this.dispatchEvent("load");
865             }, this);
866             this.setVisible(false);
867             return true;
868         }
869         if(cc._rectEqualToZero(rect)) {
870             var textureSize = tmpTexture.getContentSize();
871             rect = cc.rect(0, 0, textureSize.width, textureSize.height);
872         }
873         if(size.width === 0 && size.height === 0)
874             size = cc.size(rect.width, rect.height);
875         this._capInsets = capInsets;
876         this._spriteRect = rect;
877         this._offset = offset;
878         this._spriteFrameRotated = spriteFrameRotated;
879         this._originalSize = size;
880         this._preferredSize = size;
881         this._capInsetsInternal = capInsets;
882         if(this._scale9Enabled)
883             this.createSlicedSprites();
884         else
885             this._scale9Image.initWithTexture(tmpTexture, this._spriteRect, this._spriteFrameRotated);
886 
887         this.setState(this._brightState);
888         this.setContentSize(size);
889         if(this._spritesGenerated === true) {
890             this.setOpacity(opacity);
891             this.setColor(color);
892         }
893         this._spritesGenerated = true;
894         return true;
895     },
896     /**
897      * Update the scale9Sprite with a SpriteBatchNode.
898      * @param {cc.SpriteBatchNode} batchNode
899      * @param {cc.Rect} originalRect
900      * @param {boolean} rotated
901      * @param {cc.Rect} capInsets
902      * @returns {boolean}
903      */
904     updateWithBatchNode: function (batchNode, originalRect, rotated, capInsets) {
905         if (!batchNode) {
906             return false;
907         }
908         var sprite = new cc.Sprite(batchNode.getTexture());
909         var pos = cc.p(0,0);
910         var originalSize = cc.size(originalRect.width,originalRect.height);
911 
912         var tmpTexture = batchNode.getTexture();
913         var locLoaded = tmpTexture.isLoaded();
914         this._textureLoaded = locLoaded;
915         if(!locLoaded){
916             tmpTexture.addEventListener("load", function(sender){
917                 this._positionsAreDirty = true;
918                 this.updateWithBatchNode(batchNode, originalRect, rotated, capInsets);
919                 this.setVisible(true);
920                 this.setNodeDirty();
921                 this.dispatchEvent("load");
922             }, this);
923             this.setVisible(false);
924             return true;
925         }
926         return this.updateWithSprite(sprite, originalRect, rotated, pos, originalSize, capInsets);
927     },
928 
929     /**
930      * set the sprite frame of ccui.Scale9Sprite
931      * @param {cc.SpriteFrame} spriteFrame
932      * @param {cc.rect} capInsets
933      */
934     setSpriteFrame: function (spriteFrame, capInsets) {
935         // Reset insets
936         if (!capInsets)
937             capInsets = cc.rect();
938         var sprite = new cc.Sprite(spriteFrame.getTexture());
939         var locLoaded = spriteFrame.textureLoaded();
940         this._textureLoaded = locLoaded;
941         if(!locLoaded){
942             spriteFrame.addEventListener("load", function(sender){
943                 // the texture is rotated on Canvas render mode, so isRotated always is false.
944                 var preferredSize = this._preferredSize, restorePreferredSize = preferredSize.width !== 0 && preferredSize.height !== 0;
945                 if (restorePreferredSize) preferredSize = cc.size(preferredSize.width, preferredSize.height);
946                 this.updateWithBatchNode(this._scale9Image, sender.getRect(), cc._renderType === cc.game.RENDER_TYPE_WEBGL && sender.isRotated(), this._capInsets);
947                 if (restorePreferredSize)this.setPreferredSize(preferredSize);
948                 this._positionsAreDirty = true;
949                 this.setNodeDirty();
950                 this.dispatchEvent("load");
951             },this);
952         }
953         this.updateWithSprite(sprite, spriteFrame.getRect(),spriteFrame.isRotated(),spriteFrame.getOffset(),spriteFrame.getOriginalSize(),capInsets);
954 
955         this._insetLeft = capInsets.x;
956         this._insetTop = capInsets.y;
957         this._insetRight = this._originalSize.width - this._insetLeft - capInsets.width;
958         this._insetBottom = this._originalSize.height - this._insetTop - capInsets.height;
959     },
960 
961     //v3.3
962     /**
963      * Sets ccui.Scale9Sprite's state
964      * @since v3.3
965      * @param {Number} state
966      */
967     setState: function(state){
968         this._renderCmd.setState(state);
969     },
970     /**
971      * @brief Toggle 9-slice feature.
972      * If Scale9Sprite is 9-slice disabled, the Scale9Sprite will rendered as a normal sprite.
973      * @param {boolean}    enabled    True to enable 9-slice, false otherwise.
974      */
975     setScale9Enabled: function(enabled){
976         if (this._scale9Enabled === enabled)
977         {
978             return;
979         }
980         this._scale9Enabled = enabled;
981         this._renderers.length = 0;
982         //we must invalide the transform when toggling scale9enabled
983         cc.Node.transformDirty = true;
984         if (this._scale9Enabled) {
985             if (this._scale9Image) {
986                 this.updateWithSprite(this._scale9Image,
987                     this._spriteRect,
988                     this._spriteFrameRotated,
989                     this._offset,
990                     this._originalSize,
991                     this._capInsets);
992             }
993         }
994         this._positionsAreDirty = true;
995     },
996 
997     _setRenderersPosition: function() {
998         if(this._positionsAreDirty) {
999             this._updatePositions();
1000             this._adjustScale9ImagePosition();
1001             this._positionsAreDirty = false;
1002         }
1003     },
1004 
1005     _adjustScale9ImagePosition: function() {
1006         var image = this._scale9Image;
1007         var contentSize = this._contentSize;
1008         if(image) {
1009             image.x = contentSize.width * image.getAnchorPoint().x;
1010             image.y = contentSize.height * image.getAnchorPoint().y;
1011         }
1012     },
1013 
1014     _adjustScale9ImageScale: function() {
1015         var image = this._scale9Image;
1016         var contentSize = this._contentSize;
1017         if(image) {
1018             image.setScale(contentSize.width/image.width, contentSize.height/image.height);
1019         }
1020     },
1021 
1022     /**
1023      * Sets whether the widget should be flipped horizontally or not.
1024      * @since v3.3
1025      * @param flippedX true if the widget should be flipped horizontally, false otherwise.
1026      */
1027     setFlippedX: function(flippedX){
1028         var realScale = this.getScaleX();
1029         this._flippedX = flippedX;
1030         this.setScaleX(realScale);
1031         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
1032     },
1033 
1034     /**
1035      * <p>
1036      * Returns the flag which indicates whether the widget is flipped horizontally or not.                         <br/>
1037      *                                                                                                             <br/>
1038      * It only flips the texture of the widget, and not the texture of the widget's children.                      <br/>
1039      * Also, flipping the texture doesn't alter the anchorPoint.                                                   <br/>
1040      * If you want to flip the anchorPoint too, and/or to flip the children too use:                               <br/>
1041      * widget->setScaleX(sprite->getScaleX() * -1);                                                                <br/>
1042      * </p>
1043      * @since v3.3
1044      * @return {Boolean} true if the widget is flipped horizontally, false otherwise.
1045      */
1046     isFlippedX: function(){
1047         return this._flippedX;
1048     },
1049 
1050     /**
1051      * Sets whether the widget should be flipped vertically or not.
1052      * @since v3.3
1053      * @param flippedY true if the widget should be flipped vertically, false otherwise.
1054      */
1055     setFlippedY:function(flippedY){
1056         var realScale = this.getScaleY();
1057         this._flippedY = flippedY;
1058         this.setScaleY(realScale);
1059         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
1060     },
1061 
1062     /**
1063      * <p>
1064      * Return the flag which indicates whether the widget is flipped vertically or not.                             <br/>
1065      *                                                                                                              <br/>
1066      * It only flips the texture of the widget, and not the texture of the widget's children.                       <br/>
1067      * Also, flipping the texture doesn't alter the anchorPoint.                                                    <br/>
1068      * If you want to flip the anchorPoint too, and/or to flip the children too use:                                <br/>
1069      * widget->setScaleY(widget->getScaleY() * -1);                                                                 <br/>
1070      * </p>
1071      * @since v3.3
1072      * @return {Boolean} true if the widget is flipped vertically, false otherwise.
1073      */
1074     isFlippedY:function(){
1075         return this._flippedY;
1076     },
1077 
1078     setScaleX: function (scaleX) {
1079         if (this._flippedX)
1080             scaleX = scaleX * -1;
1081         cc.Node.prototype.setScaleX.call(this, scaleX);
1082         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
1083     },
1084 
1085     setScaleY: function (scaleY) {
1086         if (this._flippedY)
1087             scaleY = scaleY * -1;
1088         cc.Node.prototype.setScaleY.call(this, scaleY);
1089         this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.cacheDirty);
1090     },
1091 
1092     setScale: function (scaleX, scaleY) {
1093         if(scaleY === undefined)
1094             scaleY = scaleX;
1095         this.setScaleX(scaleX);
1096         this.setScaleY(scaleY);
1097     },
1098 
1099     getScaleX: function () {
1100         var originalScale = cc.Node.prototype.getScaleX.call(this);
1101         if (this._flippedX)
1102             originalScale = originalScale * -1.0;
1103         return originalScale;
1104     },
1105 
1106     getScaleY: function () {
1107         var originalScale = cc.Node.prototype.getScaleY.call(this);
1108         if (this._flippedY)
1109             originalScale = originalScale * -1.0;
1110         return originalScale;
1111     },
1112 
1113     getScale: function () {
1114         if(this.getScaleX() !== this.getScaleY())
1115             cc.log("Scale9Sprite#scale. ScaleX != ScaleY. Don't know which one to return");
1116         return this.getScaleX();
1117     },
1118 
1119     _createRenderCmd: function(){
1120         if(cc._renderType === cc.game.RENDER_TYPE_CANVAS)
1121             return new ccui.Scale9Sprite.CanvasRenderCmd(this);
1122         else
1123             return new ccui.Scale9Sprite.WebGLRenderCmd(this);
1124     }
1125 });
1126 
1127 var _p = ccui.Scale9Sprite.prototype;
1128 cc.EventHelper.prototype.apply(_p);
1129 
1130 // Extended properties
1131 /** @expose */
1132 _p.preferredSize;
1133 cc.defineGetterSetter(_p, "preferredSize", _p.getPreferredSize, _p.setPreferredSize);
1134 /** @expose */
1135 _p.capInsets;
1136 cc.defineGetterSetter(_p, "capInsets", _p.getCapInsets, _p.setCapInsets);
1137 /** @expose */
1138 _p.insetLeft;
1139 cc.defineGetterSetter(_p, "insetLeft", _p.getInsetLeft, _p.setInsetLeft);
1140 /** @expose */
1141 _p.insetTop;
1142 cc.defineGetterSetter(_p, "insetTop", _p.getInsetTop, _p.setInsetTop);
1143 /** @expose */
1144 _p.insetRight;
1145 cc.defineGetterSetter(_p, "insetRight", _p.getInsetRight, _p.setInsetRight);
1146 /** @expose */
1147 _p.insetBottom;
1148 cc.defineGetterSetter(_p, "insetBottom", _p.getInsetBottom, _p.setInsetBottom);
1149 
1150 _p = null;
1151 
1152 /**
1153  * Creates a 9-slice sprite with a texture file, a delimitation zone and
1154  * with the specified cap insets.
1155  * @deprecated since v3.0, please use new ccui.Scale9Sprite(file, rect, capInsets) instead.
1156  * @param {String|cc.SpriteFrame} file file name of texture or a cc.Sprite object
1157  * @param {cc.Rect} rect the rect of the texture
1158  * @param {cc.Rect} capInsets the cap insets of ccui.Scale9Sprite
1159  * @returns {ccui.Scale9Sprite}
1160  */
1161 ccui.Scale9Sprite.create = function (file, rect, capInsets) {
1162     return new ccui.Scale9Sprite(file, rect, capInsets);
1163 };
1164 
1165 /**
1166  * create a ccui.Scale9Sprite with Sprite frame.
1167  * @deprecated since v3.0, please use "new ccui.Scale9Sprite(spriteFrame, capInsets)" instead.
1168  * @param {cc.SpriteFrame} spriteFrame
1169  * @param {cc.Rect} capInsets
1170  * @returns {ccui.Scale9Sprite}
1171  */
1172 ccui.Scale9Sprite.createWithSpriteFrame = function (spriteFrame, capInsets) {
1173     return new ccui.Scale9Sprite(spriteFrame, capInsets);
1174 };
1175 
1176 /**
1177  * create a ccui.Scale9Sprite with a Sprite frame name
1178  * @deprecated since v3.0, please use "new ccui.Scale9Sprite(spriteFrameName, capInsets)" instead.
1179  * @param {string} spriteFrameName
1180  * @param {cc.Rect} capInsets
1181  * @returns {Scale9Sprite}
1182  */
1183 ccui.Scale9Sprite.createWithSpriteFrameName = function (spriteFrameName, capInsets) {
1184     return new ccui.Scale9Sprite(spriteFrameName, capInsets);
1185 };
1186 
1187 /**
1188  * @ignore
1189  */
1190 ccui.Scale9Sprite.POSITIONS_CENTRE = 0;
1191 ccui.Scale9Sprite.POSITIONS_TOP = 1;
1192 ccui.Scale9Sprite.POSITIONS_LEFT = 2;
1193 ccui.Scale9Sprite.POSITIONS_RIGHT = 3;
1194 ccui.Scale9Sprite.POSITIONS_BOTTOM = 4;
1195 ccui.Scale9Sprite.POSITIONS_TOPRIGHT = 5;
1196 ccui.Scale9Sprite.POSITIONS_TOPLEFT = 6;
1197 ccui.Scale9Sprite.POSITIONS_BOTTOMRIGHT = 7;
1198 
1199 ccui.Scale9Sprite.state = {NORMAL: 0, GRAY: 1};
1200